1

So, I've just figured out today that only changing state in a React Native app triggers a re-render of the component. I'm changing state, but I'm doing it from a child component, and it seems to getting stuck in some loop, and () => { this.setState({current_time:'whatever'}) doesn't seem to do anything at all. How can I change my App.js's current_time in state from TimePicker.js?

App.js

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      current_time:'initial time, unchanged in state',
    };
  }

  render() {
    let s = styles;

    return (
      <View style={s.contain}>
        <TimePicker />
        <ShowTime current_time={this.state.current_time} />
      </View>
    );
  }
}

TimePicker.js

class TimePicker extends Component {
    constructor(props){
        super(props);
    }

    render(){

        let s = styles;

        return(
            <TouchableOpacity>
                <View style={s.contain} onPress={
                    /* 

                    set this.state.current_time in parent to the actual current time
                    this.setState({current_time:'changed'}) seems to cause an infinite loop?

                    () => { this.setState({current_time:'changed'}) }  doesn't seem to do anything

                    */
                }>
                    <Text>I will change the time in state.</Text>
                </View>
            </TouchableOpacity>
        )
    }
};

ShowTime.js

class ShowTime extends Component {
    constructor(props){
        super(props);
    }

    render(){

        let s = styles;

        return(
            <View style={s.contain}>
                <Text>{this.props.current_time}</Text>
            </View>
        )
    }
};
smilebomb
  • 5,123
  • 8
  • 49
  • 81

2 Answers2

3

Create a function in App.js and pass it as prop to TimePicker Component and the purpose of this function should be to setState . e.g App.js

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      current_time:'initial time, unchanged in state',
    };
  }

currentTimeHandler = (newCurrentTime) => {
  this.setState({current_time: newCurrentTime});
}

  render() {
    let s = styles;

    return (
      <View style={s.contain}>
        <TimePicker getTime={ this.currentTimeHandler }/>
        <ShowTime current_time={this.state.current_time} />
      </View>
    );
  }
}

TimePicker.js

class TimePicker extends Component {
    constructor(props){
        super(props);
    }

    render(){

        let s = styles;

        return(
            <TouchableOpacity onPress={() => this.props.getTime('changes will be passed here')}>
                <View style={s.contain} >
                    <Text>I will change the time in state.</Text>
                </View>
            </TouchableOpacity>
        )
    }
};
Anwar Gul
  • 665
  • 4
  • 15
0

The reason is the setState only set the existing states locally in the js file. that would be your Timepicker.

In your case TimePicker is a child(or sub branch) of App (Your app stores your state, by your current build, and will never be changed by a child). You will need create two functions one in TimePicker and another App. TimePicker will handle the data and send it, via prop, the App will receive the prop and then trigger another function to setState.

Pass data from child to parent in React

This is the best one i can find.

Best read this as well: https://reactjs.org/docs/react-component.html It does say, setState only affect to local states, your state you want to set is not local.

DaemonS
  • 91
  • 1
  • 8
  • The answer from the other question doesn't appear to be working for me. – smilebomb Jul 13 '18 at 04:00
  • Try reading this one then: https://codepen.io/PiotrBerebecki/pen/dpRdKP It works, should be the same for react native – DaemonS Jul 13 '18 at 04:13
  • https://medium.com/@ruthmpardee/passing-data-between-react-components-103ad82ebd17 maybe this one too. – DaemonS Jul 13 '18 at 04:15
  • I'm following this advice, passing a function down as a prop. Then calling that function from the child. It doesn't appear to be working for me. – smilebomb Jul 13 '18 at 04:23
  • wait......... why does your View have the onpress? shouldn't it be on the Touchable? function}> – DaemonS Jul 13 '18 at 06:04