【问题标题】:ReactJS component not rerendering when props are passed传递道具时ReactJS组件不重新渲染
【发布时间】:2017-02-25 17:35:06
【问题描述】:

当我使用 Chrome 控制台在 render 方法中检查我的组件的状态时,我得到了最新的状态值。

但是,当我在 div 中显示此状态时,我得到的是原始状态值,而不是更新后的值。在 React 开发人员工具中也是如此,状态不会在那里更新。我什至尝试在shouldComponentUpdate() 方法中返回true,但没有帮助。

这是一个简化的例子:

var MyComponent = React.createClass({  
  getInitialState() {
    return { myState: "value0" };
  },
  componentWillReceiveProps(nextProps){
    if(this.state.myState != nextProps.myProp){
      this.setState({
          myState: nextProps.myProp
      }); 
    }
  },
  render: function() {
    console.log("OK - up to date myState =",this.state.myState);
    return (
        <div>NOK - original state instead of updated one: {this.state.myState}</div>
    );
  }
});

ReactDOM.render(<MyComponent myProp={"myProps"} />, document.getElementById("app")); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

您能解释一下为什么render 函数中return 之前的myState 的值是正确的,而return 之后的值不正确吗?

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    那是因为你用一个静态值初始化你的状态,你必须这样做:

    getInitialState() {
        return { myState: this.props.myProp };
    },
    

    请看下面的基本示例:

    class MyComponent extends React.Component { 
      constructor(props) {
        super(props)
        this.state = { myState: props.myProp }
      }
      
      componentWillReceiveProps(nextProps){
        if(this.state.myState != nextProps.myProp){
          this.setState({
              myState: nextProps.myProp
          });
        }
      }
      
      render () {
        console.log("OK ",this.state.myState)
        return (
            <div> NOK {this.state.myState} </div>
        );
      }
    }
    
    class App extends React.Component {
       constructor(props) {
          super(props)
          this.state = {
            value: 0
          }
       }
       render () {
          return <div>
           <button onClick={e => this.setState({ value: this.state.value + 1 }) }> Increase </button>
           <MyComponent myProp={this.state.value} />
           </div>
       }
    }
    
    ReactDOM.render(<App />, document.getElementById('app') )
    <html>
    <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    </head>
    <body>
    <div id='app'></div>
    
    </body>
    </html>

    【讨论】:

    • 嗨@Damian,我认为将道具传递给组件初始状态是一种反模式,你确定这是推荐的吗?
    • 这只是一个示例,当该值在组件周期中不会更改时,您应该使用道具,但如果该数据可以在组件内更改,您将需要根据您的道具,这很好。
    • @Surreal 你有关于这个反模式原则的参考吗?道具可以用作您的状态所基于的初始(只读)值。但是然后......这种状态的生活还在继续:p
    • 它说不要复制道具来说明你的组件是否基于你的道具渲染。如果您只是使用道具来初始化您的状态,那就可以了。基本上,他们试图避免在正确的值、道具或状态之间存在可能的问题......
    【解决方案2】:

    我想我明白为什么你在解决问题时遇到了麻烦。

    如果您想通过更改父级中的myProp 来更改MyComponent 中的值,那么使用componentWillReceiveProps 就在正确的轨道上。这是你想要做的:

    1. getInitialState 中使用myProp 初始化组件状态
    2. 使用componentWillReceiveProps根据父级传递的新道具改变状态(但接下来的问题是:你如何管理当前状态和新道具之间的差异?也许你不想重置修改后的状态)

    那么你的代码应该可以工作了。

    我附上了一个如何做的例子:

    https://jsfiddle.net/x3ef71L4/4/

    【讨论】:

      【解决方案3】:

      使用 componentWillMount() 代替构造函数为我工作

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-01
        • 2023-04-11
        • 2020-06-20
        • 1970-01-01
        • 2021-09-08
        • 2021-01-19
        相关资源
        最近更新 更多