从孩子更改父母的状态时,父母为什么不再次渲染?

时间:2018-07-03 03:13:38

标签: javascript ios reactjs class react-native

我有一个父类,该父类将名为editClassInfo的函数传递给子类。此函数绑定到父级,并且在调用时不变地更改父级的状态。但是,父级不会再次渲染,而必须从父级内部设置状态。

具体来说,问题在于具有textInput的模式组件,该组件在更改文本时设置父屏幕的状态。但是,关闭模式时,即使状态发生变化,屏幕状态也不会立即更新。相反,必须调用另一个this.setState()才能使渲染再次发生。

以下是该问题的图片参考: https://imgur.com/a/oCHRTIu

代码如下:

这是父组件。

export default class Classes extends Component {
  static navigationOptions = {
    title: 'Classes'
  };

  constructor() {
    super();

    this.state = {
      numObjects: 3.,
      classes: [
        {
          className: "Math",
          teacherName: "Someone",
        },
        {
          className: "Science",
          teacherName: "Someone",
        },
        {
          className: "Art",
          teacherName: "Someone",
        }
      ]
    };

    this.editClassInfo = this.editClassInfo.bind(this);
  }

  editClassInfo(index, infoType, value) {
    let newClass = this.state.classes;
    switch (infoType) {
      case 'className':
        newClass[index].className = value;
        break;
      case 'teacherName':
        newClass[index].teacherName = value;
        break;
    }
    this.setState({classes: newClass});
  }

  addClass(name, name2) {
    let newClass = this.state.classes.concat({className: name, teacherName: name2});
    this.setState({classes: newClass});
  }

  loadClasses = () => {
    this.setState({
        numObjects: this.state.numObjects * 2,
    })
  }

  render(){
    const classData = this.state.classes;
    console.log(this.state.classes[0]);
    return (
      <View style={styles.container}>
        <TopBar title='Classes'/>
        <View style={styles.classHeader}>
          <Text style={styles.currentClasses}> CURRENT CLASSES </Text>
          <TouchableOpacity onPress={() => {this.addClass('World History', 'Someone')}}>
            <Image
              style = {styles.addClass}
              source={require('../resources/addClass.png')}
            />
          </TouchableOpacity>
        </View>
        <FlatList
          data = { classData }
          onEndReached = {this.loadClasses}
          keyExtractor = {(item, index) => index.toString()}
          initialNumtoRender = {3}
          renderItem = {({item}) =>
            <ClassBox
              index={this.state.classes.indexOf(item)}
              editClassInfo ={this.editClassInfo}
              className={item.className}
              teacherName={item.teacherName}
            />
          }
        />
      </View>
    );
  }
}

我将editClassInfo传递到名为ClassBox的组件上:

export default class ClassBox extends Component {
  static propTypes = {
    className: PropTypes.string.isRequired,
    teacherName: PropTypes.string.isRequired,
    index: PropTypes.number.isRequired
  };

  constructor(props) {
    super(props);

    this.state = {
      isVisible: false,
    };

    this.modalVisible = this.modalVisible.bind(this);
  }

  modalVisible(visible) {
    this.setState({isVisible: visible});
  }

  render(){
    return(
      <View>
        <ClassEdit
          index={this.props.index}
          editClassInfo={this.props.editClassInfo}
          isVisible={this.state.isVisible}
          modalClose={this.modalVisible}
          className={this.props.className}
          teacherName={this.props.teacherName}
        />
        <TouchableOpacity onPress={() => {this.modalVisible(true)}}>
          <View style={styles.container}>
            <Image
              source={{uri: 'http://via.placeholder.com/50x50'}}
              style={styles.classImage}
            />
            <View style={styles.classInfo}>
              <Text style={styles.className}>
                {this.props.className}
              </Text>
              <Text style={styles.teacherName}>
                {this.props.teacherName}
              </Text>
            </View>
          </View>
        </TouchableOpacity>
      </View>
    )
  }
}

此组件包含子模式ClassEdit

export default class ClassEdit extends Component {
  static propTypes = {
    index: PropTypes.number.isRequired,
    isVisible: PropTypes.bool.isRequired,
    className: PropTypes.string.isRequired,
    teacherName: PropTypes.string.isRequired
  }

  render() {
    return(
      <Modal
        animationType="none"
        transparent={false}
        visible={this.props.isVisible}
      >
        <View style={styles.container}>
          <View style={styles.closeTop}>
            <TouchableOpacity onPress={() => {
              this.props.modalClose(false);
            }}>
              <Image
                style={styles.closeIcon}
                source={require('../resources/close.png')}
              />
            </TouchableOpacity>
          </View>
          <View style={styles.classInfo}>
            <Image
              source={{uri: 'http://via.placeholder.com/150x150'}}
              style={styles.classImage}
            />
            <TextInput
              style={styles.className}
              placeholder='Class Name'
              value={this.props.className}
              onChangeText = {(className) => {this.props.editClassInfo(this.props.index, 'className', className)}}
            />
            <TextInput
              style={styles.teacherName}
              placeholder='Teacher Name'
              value={this.props.teacherName}
              onChangeText = {(teacherName) => {this.props.editClassInfo(this.props.index, 'teacherName', teacherName)}}
            />
          </View>
        </View>
      </Modal>
    );
  }
}

在最后一个称为ClassEdit的组件中,父状态被更改,但是当模式关闭时,看不到更新的状态,而是必须调用addClass来触发它。 / p>

我对react-native有点陌生,所以我的代码可能不是最好的,而且问题可能确实很简单,但是任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

let newClass = this.state.classes;创建对实际classes状态的引用,然后对其进行突变。

要以不变的方式创建新数组,可以执行以下操作:

ES6:

let newClass = [...this.state.classes];

ES5:

let newClass = [].concat(this.state.classes);