software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
9.09k stars 1.32k forks source link

useAnimatedProps doesnt update props on web #4909

Closed apatozi closed 1 year ago

apatozi commented 1 year ago

Description

The issue is occurs only on web. It works ok on android and iOS. I've first notice the issue by trying to set showsVerticalScrollIndicator that was not disapearing on web. Then i tried to work around the issue by hacking it using the role attribute (accessibilityRole on react native) and then style it using css on the web. The role didn't change either. I works the same on Reanimated 2 as on reanimated 3.

Update extra info: pointerEvents doesn't work either because at first it maps to a style with !important rule but when changed it changes the style of the element without the important and it doesn't take effect. On web on the other hand you can set pointerEvents by setting it as animated style and not setting it at all as prop or animatedprop.

Steps to reproduce

  1. Create an Animted.View
  2. add the props we are going to use as whitelisted. addWhitelistedNativeProps({accessibilityRole: true});
  3. Declare a shared value const SharedRole=useSharedValue("initial");
  4. Declare animatedProps that contain { accessibilityRole: SharedRole.value }
  5. change SharedRole using a button or any other event.
  6. inspect using dev tools and check the element attributes

Snack or a link to a repository

https://snack.expo.dev/@albi91/reanimated-useanimatedprops-web

Reanimated version

3.3.0

React Native version

0.72.3

Platforms

Web

JavaScript runtime

None

Workflow

None

Architecture

None

Build type

None

Device

None

Device model

No response

Acknowledgements

Yes

m-bert commented 1 year ago

Hi @apatozi! I've attempted to run your provided code. While it doesn't work on snack, it seems to work fine inside our example app. Do you know any other way how to reproduce this error (or do you have a repository that I could take a look at)?

apatozi commented 1 year ago

Hello @m-bert! I made a repo which reproduces the bug in both reanimated-2 and reanimated-3. Here is the link: https://github.com/apatozi/issue-reanimated-useanimatedprops-web Tell me if any more information is needed.

m-bert commented 1 year ago

Hi again @apatozi! I've prepared this PR that should fix this issue. Could you please check that?

apatozi commented 1 year ago

Hi again @apatozi! I've prepared this PR that should fix this issue. Could you please check that?

Hi again! I checked the branch locally and it worked OK for the given example.

Some other things that i noticed: I noticed another thing that might be a side effect of the new changes (as I checked the code). Now it writes as attributes even things that are not meant to be attributes. I tried to modify "showsVerticalScrollIndicator" of an Animated.ScrollView and it literally did write

<div ... showsverticalscrollindicator="true"> ...

and same similar result was with pointer events. The initial value was written as a style "pointer-events: none !important;" and the consequent changes did not make any effect as they did write as pointerevents="auto" attribute.

Anyway the things I noticed can be worked around with some CSS attribute selectors. The scrollbars can change to hidden with some attribute change combined with CSS attribute selector and pointer events can be worked around using only style for the web and props for iOS/android.

P.s: Another thing that that I am curious to know, will these changes be reflected in reanimated 2 version also ?

m-bert commented 1 year ago

Hey! I'm glad to hear that my fix works!

Yes, you are correct, added props will be named exactly as you passed them in useAnimatedProps. This is because of how setAttribute function works - we can't do much about it. However I'm happy to hear that you've already found a workaround.

Also, isn't it possible to, for example, write:

...
    return {
      role: sharedRole.value,
    };
...

instead of

...
    return {
      accessibilityRole: sharedRole.value,
    };
...

if you want to set role attribute?

As for support for Reanimated 2, we won't include this change in that version.

apatozi commented 1 year ago

Maybe you misunderstood the part where I was explaining that the fix works partially. It changes the props in the HTML elements ok, and I understand that I can change any prop this way by writing it literally. The point is that some react-native props have different meaning for the HTML. Those kind of props still do not work.

Ex: "showsVerticalScrollIndicator" is a react-native prop of the ScrollView Component that in HTML it should translate to changing the overflow style of some elements.

Another example is "pointerEvents" that in react native is a prop but in html is a style. These kind o props translate correctly in the initial values but do not change correctly even after the fix.

m-bert commented 1 year ago

Ok, I understand what You mean. The thing is, react-native-web removed setNativeProps in version 0.19, so we had to prepare our implementation. However it was meant only for useAnimatedStyle, therefore it wasn't updating any props beside this one. The PR that I've prepared does two things:

  1. Adds setAttribute to our implementation - this is why props are added exactly as they are written.
  2. Changed logic in how react-native-web implementation was called.

To summarize, if you're using react-native-web 0.19 and higher, you have to write name of the props as you would like them to appear in HTML. On the other hand, you can try to downgrade react-native-web to version below 0.19 - that should help.