react-native-stager icon indicating copy to clipboard operation
react-native-stager copied to clipboard

Conditional render of stage

Open wesleyguirra opened this issue 6 years ago • 15 comments

Hey there, there's a way to do the conditional render of a stage?

wesleyguirra avatar Aug 25 '18 19:08 wesleyguirra

you mean in the sense of skipping a stage if some condition is met? if not, you can do any logic you want inside the render props and return a null to render nothing

pocesar avatar Aug 25 '18 22:08 pocesar

Maybe skipping can be a good solution but I don't know how to do that, there is a Stage prop for this?

wesleyguirra avatar Aug 25 '18 23:08 wesleyguirra

Tried to do logic inside render prop get a TypeError: Cannot read property type of null, see: https://gist.github.com/wesleyguirra/f1cfe8ace119f04c9f6f06b5deb0ae8c

wesleyguirra avatar Aug 25 '18 23:08 wesleyguirra

I meant, inside the the Stage. all stages are collected at the parent rendering, you can't conditionally add them to Stager, and must be a direct child

pocesar avatar Aug 25 '18 23:08 pocesar

Understood, there's a way to know the stage index? so I can check at onPress of StageButtons

wesleyguirra avatar Aug 26 '18 00:08 wesleyguirra

yes, you can use <Stager onChange={(stage, direction) => {}}> to know the current stage, and you may do some logic in there (like checking the current state and acting upon it). you could also do something inside <Stage loaded={(cb) => { }}> change the parent stage or skip a stage if you must, just don't forget to call the cb

pocesar avatar Aug 26 '18 00:08 pocesar

just a heads up, although late to the party, this will come as a new functionality in 2.0 as willSkip (which defaults to false, and supports returning a promise from it)

pocesar avatar Oct 27 '18 14:10 pocesar

Instead of returning null returning an empty string seems to work.

{this.state.showstep4 ?
                        <Stage key="step4">
                            <View>
                    
                            </View>
                        </Stage> : ''
                    }

nconroy avatar Dec 07 '18 06:12 nconroy

yes, you can use <Stager onChange={(stage, direction) => {}}> to know the current stage, and you may do some logic in there (like checking the current state and acting upon it). you could also do something inside <Stage loaded={(cb) => { }}> change the parent stage or skip a stage if you must, just don't forget to call the cb

Hi @pocesar can you explain more on how do I skip a stage at "loaded"?

Thanks in advance

cassio-nuke avatar Jan 10 '19 12:01 cassio-nuke

@cassio-nuke get a ref from the Stager, so you can control it from the outside, as such

<Stager ref={(_ref) => this.stagerRef=_ref} >
   <Stage key="key" loaded={(cb) => { this.doSomeLogic() ? this.stagerRef.next() : cb() }}>
   </Stage>
</Stager>

on newer React versions (>=16.3) it's advised to use React.createRef(), but needs to use this.stagerRef.current instead and <Stager ref={this.stagerRef}>

pocesar avatar Jan 11 '19 13:01 pocesar

Works great! Thanks for sharing

cassio-nuke avatar Jan 16 '19 16:01 cassio-nuke

Hi, I have code like this in Stage: <Button onPress={() => { this.setState({ inte: 1000 }) }} /> <Text..>{this.state.inte.toString()}</Text..>

This doesn't update <Text..>, but if I go one step back, and then return to Step 2, text is rendered. I also tried with code: <Button onPress={() => { this.setState({ inte: 113 }, () => {instance.refresh}) }} />

Can you help, what I have to do in order to setState function update Stage content

ersink1989 avatar Sep 22 '19 21:09 ersink1989

you need to call the function, in that case

this.setState({
inte: 113
}, instance.refresh)
// or
this.setState({
inte: 113
}, () => {instance.refresh()})

pocesar avatar Sep 22 '19 22:09 pocesar

Sorry, but this doesn't work in my case. :( Maybe I am doing something wrong, I am new with react-native. I copy/paste your example, and just add button as you can see bellow, and it still doesn't work. Can you check it please:

          <Stager onChange={(stage, direction) => {
                }}>
                  <Stage key="step 1" continue={() => true}>
                    {({ instance, context }) => (
                      <View>
                        <TouchableOpacity onPress={context.notify}>
                          <Text>{"Hello"}</Text>
                          <Button  onPress={() => {this.setState({
                                                    inte: String(113)
                                                    }, () => {instance.refresh()})}} />

                          <Text>{this.state.inte}</Text> 
                        </TouchableOpacity>
                      </View>
                    )}
                  </Stage>
                  <Stage key="step 2" noPrevious loaded={(cb) => this.setState({ loaded: true }, cb)}>
                    {() => (
                      <Text>{'World'}</Text>
                    )}
                  </Stage>
                </Stager>

ersink1989 avatar Sep 23 '19 07:09 ersink1989

there's two click handlers, and the first one will be the button

<Button  onPress={() => {this.setState({
   inte: String(113)
}, () => {instance.refresh()})}} />

this is stopping the propagation to the parent TouchableOpacity. You can either remove the TouchableOpacity and put context.notify() inside your button, or remove the button from inside the TouchableOpacity and put it somewhere else. or you can use context.notify instead of refresh

<Button  onPress={() => {
   this.setState({
      inte: String(113)
   }, context.notify)
}}  /> // re-indented for clarity

pocesar avatar Sep 23 '19 08:09 pocesar