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

Cannot add new property '__reanimatedHostObjectRef' #1517

Closed
rpavlovs opened this issue Dec 8, 2020 · 18 comments
Closed

Cannot add new property '__reanimatedHostObjectRef' #1517

rpavlovs opened this issue Dec 8, 2020 · 18 comments

Comments

@rpavlovs
Copy link

rpavlovs commented Dec 8, 2020

Description

I can't use an array of objects coming in through a prop inside worklets. A prop with a simple value like a number works fine. Also making a deep copy with JSON.parse(JSON.stringify(props.items)) solves the problem.

Looks like Reanimated tries to add a property on an immutable prop object and fails.

Steps to reproduce

type Props = { 
  items: Item[]
}
const MyComponent = ({ items }: Props) => {

  const foo = () => {
    'worklet'
    const item = items[0] // <-- this line causes the error
  }

  return ...
}

Expected behavior

I should be able to use any type of props in worklets

Actual behavior

Cannot add new property '__reanimatedHostObjectRef'

Package versions

@github-actions
Copy link

github-actions bot commented Dec 8, 2020

Issue validator - update # 4

Hello!
Congratulations! Your issue passed the validator! Thank you!

@karol-bisztyga
Copy link
Contributor

karol-bisztyga commented Dec 9, 2020

React Native Reanimated: installed from #1469

I don't think we should handle problems that come from unmerged changes. If you have issues with the code from that PR, please mention them there. Once it's merged and the problem persists, please reopne this issue or open the new one. Thank you 🙏

@mrousavy
Copy link
Contributor

@rpavlovs are you still experiencing this issue? Can you confirm that it actually does work with JSC, but doesn't work with Hermes?

@rpavlovs
Copy link
Author

Hey @mrousavy, it's NOT certain that this is coming from your PR.

I haven't tried Reanimated 2 with JSC at all since logs are not usable with out setup.
I've also haven't tried it on 0.64.rc-2 which I believe has an updated version of Hermes - so might potentially affect this as well.

You can check if this is still an issue by having a deeply nested object coming from props, that later gets mutated inside a worklet.

@rassemdev
Copy link

I also having this issue, when i am trying to console.log(listRef) ref of a listview.

@baronha
Copy link

baronha commented Dec 31, 2021

I also got the same error when using react-native-reanimated-carousel.

@braandl
Copy link

braandl commented Feb 15, 2022

I have made the following experience, but I can not say for sure yet if it is directly related to RA2:

When you send an Object that is used within RA2 to a native Module, it will crash, emitting this exact error.
Once you deepcopy the Object before sending it to the native module, it will not and work as expected.

Tested this with RA2.4.0

@dohooo
Copy link

dohooo commented Feb 15, 2022

I have made the following experience, but I can not say for sure yet if it is directly related to RA2:

When you send an Object that is used within RA2 to a native Module, it will crash, emitting this exact error.

Once you deepcopy the Object before sending it to the native module, it will not and work as expected.

Tested this with RA2.4.0

Cool, Maybe you can provide a minimal reproducible repository.

@jzxchiang1
Copy link

I just got this error with react-native-bottom-sheet on react-native-v8:

Error: TypeError: Cannot assign to property '__reanimatedHostObjectRef' on HostObject with default setter
This error is located at:
    in BottomSheet (created by BottomSheet)
    in PortalHost (at PortalProvider.tsx:13)
    in PortalProvider (at BottomSheetModalProvider.tsx:190)
    in BottomSheetModalProviderWrapper (at App.tsx:99)
    in AuthProvider (at App.tsx:98)
    in RNCSafeAreaProvider (at SafeAreaContext.tsx:76)
    in SafeAreaProvider (at App.tsx:97)
    in GestureHandlerRootView (at GestureHandlerRootView.android.tsx:26)
    in GestureHandlerRootView (at App.tsx:96)
    in App (at renderApplication.js:47)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:107)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:134)
    in AppContainer (at renderApplication.js:40), js engine: v8

I'm on reanimated v2.2.2.

@braandl
Copy link

braandl commented Feb 16, 2022

I currently do not have too much time, I'll try to provide one asap.

@yairopro
Copy link
Contributor

yairopro commented Feb 16, 2022

@karol-bisztyga @dohooo @braandl @rpavlovs

Here's a repo reproducing the bug: https://github.com/yairopro/reanimated-2-playground
It's a fork from the playground.

https://github.com/yairopro/reanimated-2-playground/blob/ed71b4ebb75e32e9e6ef8b0f5b468af93c7ec20d/Screen.js#L19

I may be wrong but the bug seems to come from trying to access freezed objects from inside worklet.
And components' props (unless copied) are freezed by React.

⚠️ The bug doesn't appears in debug mode.

@braandl
Copy link

braandl commented Feb 16, 2022

@yairopro Thank you very much! you might me right with the freeze-assumption, or it is some other assertion made on the objects state. Either way, this ticket should be re-opened.

@dohooo
Copy link

dohooo commented Feb 17, 2022

@yairopro Cool! Thanks!

@thisisgit
Copy link

I had the same issue when trying to assign an object or array of objects from Redux state to a shared value.

e.g. using Redux Toolkit(RTK):

// useSelector hook from RTK
const arrayOfObjects: Test[] = useSelector(selectorReturningTests);
const assignThemToMe = useSharedValue<Test[]>([]);

// Throws above error
assignThemToMe.value = arrayOfObjects;

I tried using mock data and it worked just fine. It only throws error when trying to assign value returned from RTK's selector.
While trying to figure out where the problem is coming from, I found this:
a

When an object is assigned to a shared value, that object gets mutated by reanimated and a property called __reanimatedHostObjRef gets added.
Same for array of objects, every object in the array gets that property after it is assigned to shared value.
And looks like it's being added by this function:

void addHiddenProperty(
jsi::Runtime &rt,
jsi::Value &&value,
const jsi::Object &obj,
const char *name) {
jsi::Object globalObject = rt.global().getPropertyAsObject(rt, "Object");
jsi::Function defineProperty =
globalObject.getPropertyAsFunction(rt, "defineProperty");
jsi::String internalPropName = jsi::String::createFromUtf8(rt, name);
jsi::Object paramForDefineProperty(rt);
paramForDefineProperty.setProperty(rt, "enumerable", false);
paramForDefineProperty.setProperty(rt, "value", value);
defineProperty.call(rt, obj, internalPropName, paramForDefineProperty);
}

I'm assuming that it's throwing the error because it failed to mutate the object, i.e. failed to add __reanimatedHostObjRef property.

But why this issue only occurs when trying to assign data returned from RTK?
I think it's because RTK uses immer internally, which is used to freeze the data. And this is related to #1517 (comment), where it throws the same error when trying to play around with frozen object.

Probably that's why the solution of deep copying the object/array of objects using JSON.parse(JSON.stringify(items)) works.
I think it would be better to show more readable error message if this issue doesn't get resolved anytime soon.

@dohooo
Copy link

dohooo commented Mar 25, 2022

I had the same issue when trying to assign an object or array of objects from Redux state to a shared value.

e.g. using Redux Toolkit(RTK):

// useSelector hook from RTK
const arrayOfObjects: Test[] = useSelector(selectorReturningTests);
const assignThemToMe = useSharedValue<Test[]>([]);

// Throws above error
assignThemToMe.value = arrayOfObjects;

I tried using mock data and it worked just fine. It only throws error when trying to assign value returned from RTK's selector. While trying to figure out where the problem is coming from, I found this: a

When an object is assigned to a shared value, that object gets mutated by reanimated and a property called __reanimatedHostObjRef gets added. Same for array of objects, every object in the array gets that property after it is assigned to shared value. And looks like it's being added by this function:

void addHiddenProperty(
jsi::Runtime &rt,
jsi::Value &&value,
const jsi::Object &obj,
const char *name) {
jsi::Object globalObject = rt.global().getPropertyAsObject(rt, "Object");
jsi::Function defineProperty =
globalObject.getPropertyAsFunction(rt, "defineProperty");
jsi::String internalPropName = jsi::String::createFromUtf8(rt, name);
jsi::Object paramForDefineProperty(rt);
paramForDefineProperty.setProperty(rt, "enumerable", false);
paramForDefineProperty.setProperty(rt, "value", value);
defineProperty.call(rt, obj, internalPropName, paramForDefineProperty);
}

I'm assuming that it's throwing the error because it failed to mutate the object, i.e. failed to add __reanimatedHostObjRef property.
But why this issue only occurs when trying to assign data returned from RTK? I think it's because RTK uses immer internally, which is used to freeze the data. And this is related to #1517 (comment), where it throws the same error when trying to play around with frozen object.

Probably that's why the solution of deep copying the object/array of objects using JSON.parse(JSON.stringify(items)) works. I think it would be better to show more readable error message if this issue doesn't get resolved anytime soon.

Dude, you're so cool

@aphillipo
Copy link

aphillipo commented May 26, 2022

Hello, I was having this issue when using a value generated outside of the component in a useAnimatedStyle declaration e.g.:

const data = [{ id: '1', title: 'Test', backgroundColor: 'transparent' }, { id: '2', title: 'Test another', backgroundColor: '#FF6600' }, ....etc. etc.];

const Component = () => {
    const animatedBackgroundColor = useAnimatedStyle(() => {
        const inputValues = data.map((_, index) => index);
        const outputValues = data.map((item) => item.backgroundColor);
    
        const backgroundColor = interpolateColor(
          animatedBackgroundIndex.value,
          inputValues,
          outputValues,
        );
        return {
          backgroundColor,
        };
    }, [animatedBackgroundIndex]);

    return <Animated.View style={animatedBackgroundColor}>...etc...</Animated.View>;
};

Now moving the generation of input and output values to the component everything works correctly!

const data = [{ id: '1', title: 'Test', backgroundColor: 'transparent' }, { id: '2', title: 'Test another', backgroundColor: '#FF6600' }, ....etc. etc.];

const Component = () => {
    const inputValues = data.map((_, index) => index);
    const outputValues = data.map((item) => item.backgroundColor);

    const animatedBackgroundColor = useAnimatedStyle(() => {
        const backgroundColor = interpolateColor(
          animatedBackgroundIndex.value,
          inputValues,
          outputValues,
        );
        return {
          backgroundColor,
        };
    }, [animatedBackgroundIndex]);

    return <Animated.View style={animatedBackgroundColor}>...etc...</Animated.View>;
};

Hopefully this helps someone else googling this error as to what is going on. It might be worth considering a more friendly error message for this issue!

@alexco2
Copy link

alexco2 commented Jun 9, 2022

For me this error happened when I referenced a StyleSheet object in the return object of useAnimatedStyle.

  const SnapAnimation = useAnimatedStyle(() => {
    return {
      ...styles.HeaderStyle, <- Error happened here
      transform: [
        {
          translateY: translateY.value,
        },
      ],
    };
  });

@itsramiel
Copy link

For me this error happened when I referenced a StyleSheet object in the return object of useAnimatedStyle.

  const SnapAnimation = useAnimatedStyle(() => {
    return {
      ...styles.HeaderStyle, <- Error happened here
      transform: [
        {
          translateY: translateY.value,
        },
      ],
    };
  });

I am having the same issue, using styles from stylesheet inside usAnimatedStyle recreates the issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests