octopitus / rn-sliding-up-panel

Draggable sliding up panel implemented in React Native https://octopitus.github.io/rn-sliding-up-panel/
MIT License
930 stars 157 forks source link

Using multiple Sliding-Up in one app #132

Closed AsadSaleh closed 5 years ago

AsadSaleh commented 5 years ago

Hi, thanks for this awesome component. I really liked the latest release as the API has become easier to use.

How I use your lib: Because I need it in several screen, I create a Provider and Consumer. I put the slide up inside a Provider (to handle the state) on top of my app, then pass ({ show, hide }) through it, and consume it inside my components. It worked like a charm.

Here's a glimpse of my code:

export class SlidingUpProvider extends React.Component {
  constructor(props) {
    super(props);
    this.slidingUpPanel = React.createRef(null);
    this.state = {
      id: '',
      type: '',
      show: (arg) => this.show(arg),
      hide: () => this.hide(),
    }
  }

  show = ({ id, type }) => {
    this.setState({ id, type }, 
      () => this.slidingUpPanel.current.show(height / 2)
    );
  }

  hide = () => {
    this.slidingUpPanel.current.show(0);
  }

  render() {
    const { children } = this.props;
    const { id, type } = this.state;

    return (
      <SlidingUpContext.Provider value={this.state}>
        {children}
        <SlidingUpPanel 
          ref={this.slidingUpPanel} 
          snappingPoints={[0, height / 2, height]}
          friction={0.5}
        >
          {dragHandler => (
            <View style={[styles.container]}>
              <View style={styles.dragHandler} {...dragHandler}>
                <Handle />
              </View>
              <SlidingUpContent 
                id={id} 
                type={type} 
                hide={this.hide}
              />
            </View>
          )}
        </SlidingUpPanel>
      </SlidingUpContext.Provider>
    )
  }
}

But I have a problem as my app need to use multiple slide-up.

What I do: I add a second 'slide-up' on a single component. I put different refs for both 'slide-up' (the one in the root of the app and the one in a component). On the screen that contains the second one, I drag it up to see does it work.

What I expected to happen: I hope that the second 'slide-up' scrolls as my finger drag it.

What exactly happened: When I drag it suddenly the first one appear on top of the second one, and I dragged it instead of the second one.

Can you help me with this? I really appreciate any kind of help or suggestion.

Thank you.

Environment

octopitus commented 5 years ago

You have to define animatedValue for each panel.

<SlidingUpPanel
  animatedValue={new Animated.Value(0)} // Like this
>
  // Everything else...
</SlidingUpPanel>

Note:

AsadSaleh commented 5 years ago

Thank you for your quick answer, I've implemented the 'animatedValue' prop and it works! 😄

And thanks for the note, definitely not putting Animated.Value inside render(). I put it in my constructor like this:

constructor(props) {
    super(props);
    this.slidingUpPanel = React.createRef(null);
    this._animatedValue = new Animated.Value(0);  // <-- Add this line
    this.state = {
      ...myState
    }
  }

Now I'm happy!

gilsonviana commented 3 years ago

What a shame, lost about 2 hours trying to figure this out.

Example with Hooks

const ParentComponent: React.FunctionComponent<Props> = () => {
   // Declare an array for your refs
   let refs = Array.from({length: 2}, () => useRef<SlidingUpPanel>(null))
   [...]
   // Use it like this
   const handler = (): void => refs[0].current?.show()

   return (
      <SlidingUpPanel ref={refs[0]} animatedValue={new Animated.Value(0)} />
      <SlidingUpPanel ref={refs[1]} animatedValue={new Animated.Value(0)} />
   )
}