【问题标题】:How to update (re-render) the child components in React when the parent's state change?当父级状态发生变化时,如何在 React 中更新(重新渲染)子组件?
【发布时间】:2020-03-19 05:31:56
【问题描述】:

好的,我已经知道一种方法可以做到这一点。但是,我问这个以防我重新发明轮子,因为我对 React 很陌生。我的印象是,如果父组件通过 props 将其状态传递给子组件,而不是更新父组件的状态,则子组件将在需要时重新渲染。但情况似乎并非如此。我设置了这个例子,

class Child extends Component {
  constructor(props) {
    super(props);
    this.state = {
      number: props.number,
    };
  }

  updateNumber(n) {
    this.setState({number: n});
  }

  render() {
    return (<h1>{this.state.number}</h1>);
  }
}

class Parent extends Component {

  constructor(props) {
    super(props);
    this.state = {
      number: -1,
    };
    this.child = React.createRef();
    setInterval(this.updateState.bind(this), 1000);
  }

  updateState() {
    console.log(this.state);
    this.setState({
      number: Math.floor((Math.random() * 10) + 1),
    });
    // this.child.current.updateNumber(this.state.number);
  }

  render() {
    return (
      <div>
        <Child ref={this.child} number={this.state.number}/>
      </div>
    );
  }
}

在这个例子中,除非我明确定义一个引用并使用它来调用孩子的更新函数(注释部分),否则每次更新父母的状态时都不会重新渲染孩子。是这样吗?您是想手动更新孩子的状态(呵呵),还是如果他们的父母的状态作为道具传递给他们,他们应该自动更新(并因此重新渲染)。

【问题讨论】:

  • 所以基本上你是想在你的子组件中更新你父母的状态?
  • 好吧,我不确定我是否会这样说。我将父变量的值传递给孩子。然后 child 呈现该值。假设将来父项中的变量更改了值,子项不应该根据父项的更改在屏幕上相应地更新自己。我正在尝试找出 props 是按值传递还是按引用传递,这是否有意义?
  • 这是因为您的子组件也在使用自己的状态。你应该使用 props.number 来代替
  • 是的,我需要使用孩子的道具而不是将它们存储到他们的状态中。我假设 props 仅用于传递数据,实际使用的所有内容都应存储在状态中。

标签: javascript reactjs react-props react-component react-state


【解决方案1】:

这是因为您的 Child 组件也使用了自己的状态。总是问自己是否需要state,这是 React 初学者的常见错误。

希望您可以通过查看此示例更多地了解它。我建议您不要在构造函数中调用setInterval,而是在componentDidMountclearInterval 中调用它componentWillUnmount

// Since you are not using state, you can use functional component for your Child component
const Child = ({ number }) => <h1>{number}</h1>;

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.timer = null;
    this.state = { number: 0 };
  }

  componentDidMount() {
    // setInterval after component did mount
    this.timer = setInterval(this.incrementNumber, 1000);
  }

  componentWillUnmount() {
    // clearInterval when component is going to unmount
    if (this.timer) {
      clearInterval(this.timer);
    }
  }

  incrementNumber = () => {
    // setState function callback to ensure state received will be latest state
    this.setState(prevState => ({ number: prevState.number + 1 }));
  }

  render() {
    const { number } = this.state;
    return (
      <div>
        <Child number={number} />
      </div>
    );
  }
}

【讨论】:

  • 我明白了,但是当您设置 setInterval(this.incrementNumber, 1000) 时,您不必将 this 绑定到像 setInterval(this.incrementNumber.bind(this), 1000) 这样的增量函数,这样您就可以在 @ 中使用 this.setState 987654334@?
  • @scribe 看看this关于使用箭头函数的解释。这应该回答你的问题
【解决方案2】:

重新渲染孩子的一个简单选择是每次需要重新渲染时更新唯一键属性。

&lt;ChildComponent key={this.state.updatedKey}/&gt;

【讨论】:

    【解决方案3】:

    您的方法是错误的,不要像这样从子状态更新您的父状态,也不要将道具保存在子状态中,它们已经随着父更新而更新。

    如果你想更新父表单子传递道具表单子到父这样。当父更新时,子也会更新。

    class Child extends Component {
      constructor(props) {
        super(props);
      }
    
    updateNumber=()=>{// update parent form child. call this function in somewhere in your component. if you want to pass event pass it as second argument
      this.props.updateNumber(newUpdatedNumber,event);
    }
    
      render() {
        return (<h1>{this.props.number}</h1>);
      }
    }
    
    class Parent extends Component {
    
      constructor(props) {
        super(props);
        this.state = {
          number: -1,
        };
        this.child = React.createRef();
        setInterval(this.updateState.bind(this), 1000);
      }
    
      updateState() {
        console.log(this.state);
        this.setState({
          number: Math.floor((Math.random() * 10) + 1),
        });
      }
    //update parent from child
    
      updateParentFromChild=(updatedNumber,event)=>{//catch function from child 
       this.setState({
          number:updatedNumber
       });
      }
    
    
      render() {
        return (
          <div>
            <Child ref={this.child} updateNumber={this.updateParentFromChild} number={this.state.number}/>
          </div>
        );
      }
    }
    

    【讨论】:

    • 我想你误解了我一点,引用你的话:“你的方法是错误的,不要像这样从孩子更新你的父母状态”。我没有这样做(所以我认为),我的问题不是试图从孩子那里更新父母。但是,正如您所说,“并且不要将道具保存在子状态中,它们已经随着父更新而更新。”,这是我的问题。
    • 那么你就可以在你的子组件中使用 this.props.propName
    • 但在某些项目中,您需要从孩子更新父状态,因此答案就在这里
    猜你喜欢
    • 2021-07-09
    • 1970-01-01
    • 2021-01-27
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 2019-12-14
    相关资源
    最近更新 更多