Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Patch AnimatedStyle to avoid discarding the initial style info #35198

Closed

Conversation

gabrieldonadel
Copy link
Collaborator

Summary

This PR patches AnimatedStyle to avoid discarding the initial style information which destroys the output of web-style compilers and breaks rendering, as requested on #34425. This uses a slightly modified version of a patch used by react-native-web necolas/react-native-web@4c678d2.

Changelog

[General] [Fixed] - Patch AnimatedStyle to avoid discarding the initial style info

Test Plan

Run yarn jest Animated and ensure CI is green

image

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 4, 2022
@analysis-bot
Copy link

analysis-bot commented Nov 4, 2022

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 7,070,315 -31,948
android hermes armeabi-v7a 6,442,768 -28,676
android hermes x86 7,485,557 -34,042
android hermes x86_64 7,345,103 -32,923
android jsc arm64-v8a 8,934,976 -32,057
android jsc armeabi-v7a 7,669,092 -28,785
android jsc x86 8,995,029 -34,166
android jsc x86_64 9,473,961 -33,049

Base commit: e504141
Branch: main

@analysis-bot
Copy link

analysis-bot commented Nov 4, 2022

Platform Engine Arch Size (bytes) Diff
ios - universal n/a --

Base commit: e504141
Branch: main

@pull-bot
Copy link

pull-bot commented Nov 4, 2022

PR build artifact for bdc9819 is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@javache
Copy link
Member

javache commented Nov 4, 2022

Please provide a unit tests that shows how this behaviour was broken before and how this change resolves it. This will help me understand the goal here and prevent us from breaking it in the future :)

@gabrieldonadel
Copy link
Collaborator Author

Please provide a unit tests that shows how this behaviour was broken before and how this change resolves it. This will help me understand the goal here and prevent us from breaking it in the future :)

@necolas would you mind helping me with this one? I know that the problem is described on necolas/react-native-web#2387 but I'm not completely sure how to recreate that scenario on this repo

_style: Object;

constructor(style: any) {
super();
style = flattenStyle(style) || ({}: {[string]: any});
Copy link
Contributor

@necolas necolas Nov 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On web, using flattenStyle creates a new object each time which causes correctness and perf issues:

  1. It mixes inline and compiled styles into a single object.
  2. The style runtime can no longer recognize the style object as static / pre-compiled.
  3. The style runtime can no longer cache the result of style merges involving this style.

Comment on lines +21 to +36
function createAnimatedStyle(inputStyle: any): Object {
const style = flattenStyle(inputStyle);
const animatedStyles: any = {};
for (const key in style) {
const value = style[key];
if (key === 'transform') {
animatedStyles[key] = new AnimatedTransform(value);
} else if (value instanceof AnimatedNode) {
animatedStyles[key] = value;
} else if (value && !Array.isArray(value) && typeof value === 'object') {
animatedStyles[key] = createAnimatedStyle(value);
}
}
return animatedStyles;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Animated nodes can only exist on inline styles, this function plucks them out of the provided styles and places them into a separate object that can be appended to the original input styles.

Libraries/Animated/nodes/AnimatedStyle.js Outdated Show resolved Hide resolved
@necolas
Copy link
Contributor

necolas commented Nov 4, 2022

Please provide a unit tests that shows how this behaviour was broken before and how this change resolves it. This will help me understand the goal here and prevent us from breaking it in the future :)

The behavior is broken on web because using flattenStyle is fundamentally incompatible with any approach to compiling styles to CSS. necolas/react-native-web#2387

A unit test for this change in RN would only show that Animated nodes are duplicated in a new style object appended to the input styles, and that the return from the Style node is an array instead of an object. There would be no functional difference on native.

@pull-bot
Copy link

pull-bot commented Nov 8, 2022

PR build artifact for c47a9f4 is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@pull-bot
Copy link

pull-bot commented Nov 8, 2022

PR build artifact for c45bf58 is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@pull-bot
Copy link

pull-bot commented Nov 9, 2022

PR build artifact for b45837a is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

Libraries/Animated/__tests__/Animated-web-test.js Outdated Show resolved Hide resolved
Libraries/Animated/nodes/AnimatedStyle.js Outdated Show resolved Hide resolved
Libraries/Animated/nodes/AnimatedStyle.js Outdated Show resolved Hide resolved
@javache
Copy link
Member

javache commented Nov 10, 2022

Does this correctly handle scenarios like this?

style={[
   {backgroundColor: animatedValue},
   {backgroundColor: 'red'},
]}

The expected outcome would be that animatedValue is not used.

@necolas
Copy link
Contributor

necolas commented Nov 10, 2022

Yes, it does. The first thing we do is a flatten, and then extract any animated values that are left

@pull-bot
Copy link

PR build artifact for 45e8c02 is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@gabrieldonadel
Copy link
Collaborator Author

@necolas FYI this should be good for another review round

Libraries/Animated/__tests__/Animated-web-test.js Outdated Show resolved Hide resolved
Comment on lines 138 to 156
it('does not discard initial style', () => {
const value1 = new Animated.Value(1);
const scale = value1.interpolate({
inputRange: [0, 1],
outputRange: [1, 2],
});
const callback = jest.fn();
const node = new AnimatedProps(
{
style: {
transform: [
{
scale,
},
],
},
},
callback,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test will be a bit confusing without changes / explanation. The behavior matters when the input style is a mix of values from StyleSheet.create (ie contains no animated values, could be optimized to another format) and an inline style with an animation

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I've updated tests a bit to include StyleSheet.create

@pull-bot
Copy link

PR build artifact for 5b6fede is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@pull-bot
Copy link

PR build artifact for 650c45e is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

Libraries/Animated/nodes/AnimatedStyle.js Outdated Show resolved Hide resolved
@pull-bot
Copy link

PR build artifact for 11daeda is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@gabrieldonadel
Copy link
Collaborator Author

Hi @cipolleschi, do you mind importing this PR? 😅

@facebook-github-bot
Copy link
Contributor

@javache has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@gabrieldonadel gabrieldonadel deleted the fix/patch-animated-style branch November 18, 2022 15:44
OlimpiaZurek pushed a commit to OlimpiaZurek/react-native that referenced this pull request May 22, 2023
…acebook#35198)

Summary:
This PR patches `AnimatedStyle` to avoid discarding the initial style information which destroys the output of web-style compilers and breaks rendering, as requested on facebook#34425. This uses a slightly modified version of a patch used by react-native-web  necolas/react-native-web@4c678d2.

## Changelog

[General] [Fixed] - Patch AnimatedStyle to avoid discarding the initial style info

Pull Request resolved: facebook#35198

Test Plan:
Run `yarn jest Animated` and ensure CI is green

![image](https://user-images.githubusercontent.com/11707729/199869612-4f2302da-5791-492f-83a7-683305757c23.png)

Reviewed By: necolas

Differential Revision: D41379826

Pulled By: javache

fbshipit-source-id: 7e16726828b98def14847ec3499ff93777a9cbfb
facebook-github-bot pushed a commit that referenced this pull request Oct 25, 2023
…41176)

Summary:
#35198 introduced a regression where if an `{transform: undefined}` style is provided to an Animated View a `Cannot read property 'map' of undefined` type error is thrown

<img src="https://github.com/facebook/react-native/assets/11707729/bb87781e-1ba7-40ec-879d-a57cef3e10d9" height="200" />

## Changelog:

[GENERAL] [FIXED] - Fix `createAnimatedStyle` when providing an undefined transform style

Pull Request resolved: #41176

Test Plan:
<details>
  <summary>Render an `Animated.View` passing `style={{transform: undefined}}`</summary>

E.g.

```
const UndefinedTransform = () => {
  return (
    <View>
      <Animated.View style={{transform: undefined}} />
    </View>
  );
};
```
</details>

### RNTester
1. Open the RNTester app and navigate to the Animated page
2. Navigate to the Transform Styles page
3. App should not throw any errors

<table>
    <tr><th>Before</th><th>After</th></tr>
    <tr>
        <td><video src="https://github.com/facebook/react-native/assets/11707729/92ba9c3b-60b0-4805-8080-0e7fb7c00345"/></td>
        <td><video src="https://github.com/facebook/react-native/assets/11707729/80e2bba8-6ff6-4cf5-bcb8-26de0b869036"/></td>
    </tr>
</table>

Reviewed By: fabriziocucci

Differential Revision: D50638415

Pulled By: javache

fbshipit-source-id: 0ee949f019a77b8bef557888694e0e8404810105
Othinn pushed a commit to Othinn/react-native that referenced this pull request Oct 30, 2023
…acebook#41176)

Summary:
facebook#35198 introduced a regression where if an `{transform: undefined}` style is provided to an Animated View a `Cannot read property 'map' of undefined` type error is thrown

<img src="https://github.com/facebook/react-native/assets/11707729/bb87781e-1ba7-40ec-879d-a57cef3e10d9" height="200" />

## Changelog:

[GENERAL] [FIXED] - Fix `createAnimatedStyle` when providing an undefined transform style

Pull Request resolved: facebook#41176

Test Plan:
<details>
  <summary>Render an `Animated.View` passing `style={{transform: undefined}}`</summary>

E.g.

```
const UndefinedTransform = () => {
  return (
    <View>
      <Animated.View style={{transform: undefined}} />
    </View>
  );
};
```
</details>

### RNTester
1. Open the RNTester app and navigate to the Animated page
2. Navigate to the Transform Styles page
3. App should not throw any errors

<table>
    <tr><th>Before</th><th>After</th></tr>
    <tr>
        <td><video src="https://github.com/facebook/react-native/assets/11707729/92ba9c3b-60b0-4805-8080-0e7fb7c00345"/></td>
        <td><video src="https://github.com/facebook/react-native/assets/11707729/80e2bba8-6ff6-4cf5-bcb8-26de0b869036"/></td>
    </tr>
</table>

Reviewed By: fabriziocucci

Differential Revision: D50638415

Pulled By: javache

fbshipit-source-id: 0ee949f019a77b8bef557888694e0e8404810105
lunaleaps pushed a commit that referenced this pull request Nov 3, 2023
…41176)

Summary:
#35198 introduced a regression where if an `{transform: undefined}` style is provided to an Animated View a `Cannot read property 'map' of undefined` type error is thrown

<img src="https://github.com/facebook/react-native/assets/11707729/bb87781e-1ba7-40ec-879d-a57cef3e10d9" height="200" />

## Changelog:

[GENERAL] [FIXED] - Fix `createAnimatedStyle` when providing an undefined transform style

Pull Request resolved: #41176

Test Plan:
<details>
  <summary>Render an `Animated.View` passing `style={{transform: undefined}}`</summary>

E.g.

```
const UndefinedTransform = () => {
  return (
    <View>
      <Animated.View style={{transform: undefined}} />
    </View>
  );
};
```
</details>

### RNTester
1. Open the RNTester app and navigate to the Animated page
2. Navigate to the Transform Styles page
3. App should not throw any errors

<table>
    <tr><th>Before</th><th>After</th></tr>
    <tr>
        <td><video src="https://github.com/facebook/react-native/assets/11707729/92ba9c3b-60b0-4805-8080-0e7fb7c00345"/></td>
        <td><video src="https://github.com/facebook/react-native/assets/11707729/80e2bba8-6ff6-4cf5-bcb8-26de0b869036"/></td>
    </tr>
</table>

Reviewed By: fabriziocucci

Differential Revision: D50638415

Pulled By: javache

fbshipit-source-id: 0ee949f019a77b8bef557888694e0e8404810105
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants