简体   繁体   中英

How to re-render child component when Parent state is changed?

I have Parent component which include child component aswell. I pass some props to child component from parent. My problem is when i change slider to get new value on parent component, re render does not work on Parent. this causes not re render child component as well.

when changing slider, the function get executed and state is changed with new value. But this setstate is not trigger rerender. I am debugging the below code, console logs are like this(changing slider to 1 from 0);

delay -> 0
delay timetypes -> 0  (6 times executed)
delay -> 1

and when i touch one of the touchable opacities,gets this.state.delay = 0 but i changed 0 to 1 via slider.

// welcome.js

export default class welcome extends Component {
  constructor(props) {
    super(props);
    this.state = {
      GridViewItems: [
        { key: "1 min game", min: 1, sec: 0 },
        { key: "3 min game", min: 3, sec: 0 },
        { key: "5 min game", min: 5, sec: 0 },
        { key: "7 min game", min: 7, sec: 0 },
        { key: "10 min game", min: 10, sec: 0 },
        { key: "15 min game", min: 15, sec: 0 }
      ],
      value : 0
    };
  }

  GetGridViewItem(item) {
    Alert.alert(item);
  }

  change(value) {
    console.log("change value -> " + value );
    this.setState({
      value: value
  })}

  render() {
    console.log("delay -> " + this.state.value);
    return (

      <View style={styles.MainContainer}>
        <Text style={styles.welcomeText}>Welcome ChessClock</Text>
        <Text style={styles.text}>Delay Time: {this.state.value}</Text>
        <Slider
          style = {styles.slider}
          step={1}
          maximumValue={20}
          value={this.state.value}
          onValueChange={(val)=> this.setState({value: val})}
        />
        <FlatList
          data={this.state.GridViewItems}
          renderItem={({ item }) => (
            <TimerTypes
              navigation={this.props.navigation}
              BlockStyle={styles.GridViewBlockStyle}
              TextStyle={styles.GridViewInsideTextItemStyle}
              title={item.key}
              time={item.min * 60 + item.sec}
              delay = {this.state.value}
            />
          )}
          numColumns={2}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    justifyContent: "center",
    flex: 1,
    margin: 10,
    paddingTop: Platform.OS === "ios" ? 20 : 0
  },
  GridViewBlockStyle: {
    justifyContent: "center",
    flex: 1,
    alignItems: "center",
    height: 100,
    margin: 5,
    backgroundColor: "#05BC87"
  },
  GridViewInsideTextItemStyle: {
    color: "#fff",
    padding: 10,
    fontSize: 18,
    justifyContent: "center"
  },
  welcomeText: {
    color: "#0F2284",
    padding: 60,
    fontSize: 30,
    justifyContent: "center",
    textAlign: "center"
  },
  text: {
    fontSize: 20,
    justifyContent: "center",
    marginLeft:10
  },
  slider: {
    width: '100%',
    marginBottom: 25,
    justifyContent: "center",
    alignItems : "center"
  }
});



// timeTypes

export default class timeTypes extends Component {
    constructor(props) {
        super(props);
        this.state = {
            delay : props.delay
        }
    }

    componentWillReceiveProps(nextProps) {
        this.setState({ delay: nextProps.delay });  
      }

    render() {
        console.log("delay timetypes -> " + this.props.delay);
        console.log("delay timetypes -> " + this.state.delay);
        return (
            <TouchableOpacity onPress={() => this.props.navigation.navigate('Home', {
                time: this.props.time,
                delay : this.state.delay
            })}
            style={this.props.BlockStyle} >
                <Text style={this.props.TextStyle}>
                    {this.props.title}
                </Text>
            </TouchableOpacity >
        );
    }
}

The happy path should be when changing slider to get new number, parent will rerender and child should get the new value.

github repo: https://github.com/Erkanerkisi/ChessClock

According to the docs:

FlatList is a PureComponent which means that it will not re-render if props remain shallow-equal. Make sure that everything your renderItem function depends on is passed as a prop (eg extraData) that is not === after updates, otherwise your UI may not update on changes. This includes the data prop and parent component state.

So try adding extraData={ this.state.value } to your FlatList component

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM