software-mansion / react-native-reanimated

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

[3.12.0] TypeError: property is not configurable on useAnimatedStyle hook #6066

Closed efstathiosntonas closed 3 weeks ago

efstathiosntonas commented 1 month ago

Description

When spreading ...StyleSheet.absoluteFillObject on useAnimatedStyle hook it crashes with TypeError: property is not configurable, it used to work fine on 3.11.x.

  const animatedGradientStyle = useAnimatedStyle(() => {
    return {
      ...StyleSheet.absoluteFillObject,
      flexDirection: "row",
      transform: [
        {
          translateX: interpolate(
            animatedValue.value,
            [0, 1],
            direction === "right"
              ? [-animationWidth, animationWidth]
              : [animationWidth, -animationWidth]
          )
        }
      ]
    };
  });

If I move the spread in the Animated.View style={} then it works fine.

let me know if you want the whole component, it's a Skeleton placeholder, I injected the spread on other useAnimatedStyle hooks in other places of the app and it crashes so I don't think it's component/bad code issue.

probably relevant:

Steps to reproduce

  1. use 3.12.0
  2. spread an object inside useAnimatedStyle hook

Snack or a link to a repository

no repro

Reanimated version

3.12.0-nightly-20240528-4cd750504

React Native version

0.74.1

Platforms

Android, iOS

JavaScript runtime

Hermes

Workflow

React Native

Architecture

Paper (Old Architecture)

Build type

Debug app

Device

iOS simulator

Device model

No response

Acknowledgements

Yes

github-actions[bot] commented 1 month ago

Hey! πŸ‘‹

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?

efstathiosntonas commented 1 month ago

@piaskowyk can you please take a look into this? (tagging you since you fixed the similar linked issue).

It happens with runOnJS too, eg:

const [showPlayButton, setShowPlayButton] = useState(!user?.gif_autoplay);
const [currentIndex, setCurrentIndex] = useState(0);

const selectedPageHandler = useAnimatedPagerSelectedPageHandler({
    onPageSelected: (e) => {
      "worklet";
      currentPage.value = e.position;
      runOnJS(setShowPlayButton)(!user?.gif_autoplay);
      runOnJS(setCurrentIndex)(e.position);
    }
  });

This line will throw: tsx runOnJS(setShowPlayButton)(!user?.gif_autoplay); while the next line won't.

TomCorvus commented 1 month ago

I have the same problem since 3.12.0 version. To reproduce this error, just call a variable from StyleSheet.create to set a property value in useAnimatedStyle hook. Like this:

export const useStyles = () => {
    const styles = StyleSheet.create({
        container: {
            marginTop: 16
        } as ViewStyle,
    })
    return styles
}
export default useStyles
const animatedStyle = useAnimatedStyle(() => ({
    marginTop: styles.container.marginTop,
    opacity: interpolate(
        scrollOffsetY.value,
        [0, TOP_SCROLL_DISTANCE],
        [0, 1],
        Extrapolation.CLAMP,
    ),
}))

@szydlovsky Did you see this issue before releasing 3.12.0 version?

quocluongha commented 1 month ago

I also encounter the same problem after upgrading from 3.11.x to 3.12.0. For me it happened when I try to call a function exposed by a component via its ref, using React.createRef.

Modal.tsx

export const ModalRef = createRef()

export const Modal = props => {
  return <ModalComponent ref={BottomTabBarRef} {...props} />
};

App.tsx

<>
  <Child />
  <Modal />
</>

Child.tsx

useAnimatedReaction(
  () => ({...}),
  ({ ... }) => {
     runOnJS(ModalRef.current.show)() // <-- Works fine before upgrading to 3.12.0
  }
);
MichaelDanielTom commented 1 month ago

I also experienced this while trying to use StyleSheet.hairlineWidth within useAnimatedStyle. One thing to note is that it did not need to actually be called to crash, only to be somewhere in the code in the worklet. A temporary workaround for me was to define const hairlineWidth = StyleSheet.hairlineWidth; outside of the worklet, and then use that value in the worklet, so I'd assume this would work for StyleSheet.absoluteFillObject.

akuul commented 4 weeks ago

Encountered same issue with 3.12.0.

Minimal snippet to reproduce error:

const animatedSwitchKnob = useAnimatedStyle(() => {
    const [offsetLeft, offsetRight] = [
      styles.inner.paddingStart,
      styles.inner.paddingEnd,
    ];
   <...>
  }, [activated]);
  const styles = StyleSheet.create({
    inner: {
      paddingStart: 4,
      paddingEnd: 4,
    },
});
efstathiosntonas commented 4 weeks ago

@tjzel @kmagiera sorry for breaking balls about this issue, is someone looking into it? It's impossible to work πŸ˜“

I could downgrade to 3.11.x but why should I? haha

giantslogik commented 4 weeks ago

Patch package that fixed a similar issue: https://github.com/software-mansion/react-native-reanimated/issues/6082#issuecomment-2151894668

efstathiosntonas commented 4 weeks ago

I think we should check if the property is configurable on shareables.ts freezeObjectIfDev function:

https://github.com/software-mansion/react-native-reanimated/blob/8a9e161a7ab0cabe19744eb21c7a59aaed1f3376/src/reanimated2/shareables.ts#L320-L321

Object.entries(value).forEach(([key, element]) => {
    const descriptor = Object.getOwnPropertyDescriptor(value, key);
    if (descriptor && !descriptor.configurable) {
      return;
    }
...
tjzel commented 3 weeks ago

I hate it when property is not configurable

tjzel commented 3 weeks ago

I've just released an rc1 version of Reanimated (3.13.0-rc.1) that should solve this issue. Please check if it works for you.

efstathiosntonas commented 3 weeks ago

Thanks @tjzel! Been using

if (descriptor && !descriptor.configurable) {
      return;
    }

from comment above since I posted the comment and no issues so far so 3.13.0-rc.1 should be fine!

tjzel commented 2 weeks ago

3.12.1 containing the fix is out!