Search code examples
javascriptreactjsreact-nativeecmascript-6react-state-management

Stuck While lifting state up in React Native


I'm creating a sample react application for learning purpose, in that I've following hierarchy of separate components:

<RadioButton>
   //Radio buttons are rendered here and selection of radio buttons are maintained in state of this component
</RadioButton>

<SelectCard>
    <RadioButton dataToPopulate = ['choice A', 'choice B'] />
</SelectCard>

<ParentSelectCard>
    <SelectCard /> //Rendering SelectCard with passing some data as prop from here
</ParentSelectCard>

<Button />  //Custom button component

<HomeScreen>
    <ParentSelectCard />
    <Button />
</HomeScreen>

Now when I press the button, I want to navigate to other screen by passing the selected options in radio buttons.

I've read this article about lifting state up. But the problem is, here there is no common parent ancestor to which I can lift the state to.

If I list the state up to <HomeScreen> component, How can I manage the selections made in <RadioButton> component?

Here is the complete code of <RadioButton> component:

class RadioButton extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      radioSelected: 0
    }
  }

  handleRadioClick(id) {
    this.setState({
      radioSelected: id
    });
  }

  render(){
    return this.props.dataToPopulate.map((element) => {
      return (
        <View key = {element.id} style={styles.radioButton}>
          <TouchableOpacity style={styles.radioButtonTint} onPress = {this.handleRadioClick.bind(this, element.id)}>
            { element.id === this.state.radioSelected ? (<View style={styles.radioButtonSelected}/>) : (null) }
          </TouchableOpacity>
          <Text style={styles.radioButtonText}> {element.value} </Text>
        </View>
      );
    });
  }
}

Here you can see that the final choice made will be stored in the state of this component (in radioSelected).

What I'm missing here? Is my design of <RadioButton> wrong?


Solution

  • What I'm missing here? Is my design of is wrong?

    Well if you "lift state up" the radio button itself should not have any state at all. Instead pass down a handler to the RadioButton:

     <RadioButton onChange={value => this.doSomethingWith(value)} />
    

    Then you can call that inside of the radio button whenevver something was changed, and handle the results in <App/>.

    If you have to pass down that handler through multiple levels it might be better to use a context.