react-native-shared-element icon indicating copy to clipboard operation
react-native-shared-element copied to clipboard

Basic example not working as a functional component

Open MarcHbb opened this issue 2 years ago • 3 comments
trafficstars

I tried to use the basic example with functional component and failed to to this. I saw there's already an issue discussing about it (https://github.com/IjzerenHein/react-native-shared-element/issues/9), but no answer was provide.

Using the navigation lib, everything is fine, but this librairy not. The main goal is to achieve the basic implementation so I can do more complex things.

Tried to use State, Refs but nothing is working, everytime I get errors like Error: Maximum update depth exceeded.

Repro : https://snack.expo.dev/@marc-hbb/sharedelement

EDIT : My final goal is to have a shared element transition on a view. With navigation, it seems that if I want to use it on a View (with an image inside), the image is laggy. On the other hand, on the "hero" example the shared element is a View. If there's a way to achieve this with react-navigation-shared-element please let me know ! :)

MarcHbb avatar Feb 23 '23 14:02 MarcHbb

Hey! Thanks for opening the issue. The issue doesn't seem to contain a link to a repro (a snack.expo.dev link or link to a GitHub repo under your username).

Can you provide a minimal repro which demonstrates the issue? A repro will help us debug the issue faster. Please try to keep the repro as small as possible and make sure that we can run it without additional setup.

github-actions[bot] avatar Feb 23 '23 14:02 github-actions[bot]

Hi, thanks for reporting and providing the Snack example 👍 I've had a closer look and the problem is indeed with using nodeFromRef from inside a functional component, which triggers the Maximum update depth exceeded error (as reported in #9).

I've modified the Snack to workaround this problem and saved it here: https://snack.expo.dev/@ijzerenhein/sharedelement

I replaced the ancestor <View> with a <SharedElement> node which is in fact nothing more than a component based View which translates ref into a node using nodeFromRef. This successfully mitigates the problem as you can see in the working example.

// before
<View style={styles.scene2} ref={...}>
    <SharedElement onNode={setScene2Node}>
        <Image style={styles.image2} source={require("./image.jpg")} />
    </SharedElement>
</View>

// after
<SharedElement style={styles.scene2} onNode={setScene2Ancestor}>
    <SharedElement onNode={setScene2Node}>
        <Image style={styles.image2} source={require("./image.jpg")} />
    </SharedElement>
</SharedElement>

SharedElement.tsx implementation

export class SharedElement extends React.Component<SharedElementProps> {
  componentDidUpdate(prevProps: SharedElementProps) {
    if (!prevProps.onNode && this.props.onNode && this._node) {
      this.props.onNode(this._node);
    }
  }

  private _node: SharedElementNode | null = null;

  private onSetRef = (ref: any) => {
    this._node = nodeFromRef(ref, true, this);
    if (this.props.onNode) {
      this.props.onNode(this._node);
    }
  };

  render() {
    const {
      onNode, //eslint-disable-line @typescript-eslint/no-unused-vars
      ...otherProps
    } = this.props;
    return <View ref={this.onSetRef} collapsable={false} {...otherProps} />;
  }
}

IjzerenHein avatar Mar 28 '23 14:03 IjzerenHein

@MarcHbb let me know if you're able to have everything working as you want with the changes recommended by @IjzerenHein so we can close this issue :)

p-syche avatar Mar 31 '23 11:03 p-syche