子组件在没有函数属性的情况下不会更新

时间:2017-08-21 12:48:14

标签: javascript reactjs redux react-redux

我的React组件遇到了一个非常奇怪的行为,我无法解释。

这是我应用的缩小版本:



class Child extends React.Component {
  componentDidUpdate(prev) {
    if (!prev.isActive && this.props.isActive) {
      console.log('activated', this.props.title);
    }
  }

  render() {
    return (
      <span
        className={this.props.isActive ? 'child active' : 'child'}
        onClick={this.props.onClick}
      >
        {this.props.title}
      </span>
    );
  }
}

const Child1 = reactRedux.connect((state, props) => ({
  isActive={props.isActive('Child1')}
  onClick={() => props.activate('Child1')}
  title="Child1"
}))(Child);

const Child2 = reactRedux.connect((state, props) => ({
  isActive={props.isActive('Child2')}
  onClick={() => props.activate('Child2')}
  title="Child2"
}))(Child);

class Root extends React.Component {
  state = { active: null };

  activate = (active) => {
    if (!this.isActive(active)) {
      this.setState({ active });
    }
  };

  isActive = active => this.state.active === active;

  renderChild = (ChildComponent, i) => (
    <ChildComponent
      activate={this.activate}
      isActive={this.isActive}
      key={i}
    />
  );

  render() {
    const children = [Child1, Child2];

    return (
      <reactRedux.Provider store={this.props.store}>
        <div>{children.map(this.renderChild)}</div>
      </reactRedux.Provider>
    );
  }
}

const reducer = (state, action) => ({});
const store = redux.createStore(reducer);
    
ReactDOM.render(<Root store={store} />, document.getElementById('root'));
&#13;
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.min.js"></script>
<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>
&#13;
&#13;
&#13;

好的,问题是,Child组件的componentDidUpdate没有被调用。但是,如果我将包含函数的属性传递给我的所有子属性,它就像魅力一样。

renderChild = (ChildComponent, i) => (
  <ChildComponent
    activate={this.activate}
    isActive={this.isActive}
    key={i}
    asfafasg={() => {}}
  />
);

有没有人知道这种行为的来源?真的很奇怪。我已经重新启动了我的webpack builder等,以确保这不是一个奇怪的缓存问题。

当我点击跨度时,Root组件的状态将正确更新,但是孩子的componentDidUpdate方法不会被激活。

我已经测试了它没有react-reduxs&#39;连接功能,它已经工作。所以这似乎是连接功能的一个问题。

2 个答案:

答案 0 :(得分:1)

您的代码对我来说很合适(除了您在constructor中不使用class这一事实)

&#13;
&#13;
class Child extends React.Component {
  componentDidUpdate(prev) {
    if (!prev.isActive && this.props.isActive) {
      console.log('activated', this.props.children);
    }
  }

  render() {
    return (
      <span
        className={this.props.isActive ? 'child active' : 'child'}
        onClick={this.props.onClick}
      >
        {this.props.children}
      </span>
    );
  }
}

const Child1 = props => (
  <Child
    isActive={props.isActive('Child1')}
    onClick={() => props.activate('Child1')}
  >
    Child1
  </Child>
);

const Child2 = props => (
  <Child
    isActive={props.isActive('Child2')}
    onClick={() => props.activate('Child2')}
  >
    Child2
  </Child>
);

class Root extends React.Component {
  state = { active: null };

  activate = (active) => {
    if (!this.isActive(active)) {
      this.setState({ active });
    }
  };

  isActive = active => this.state.active === active;

  renderChild = (ChildComponent, i) => (
    <ChildComponent
      activate={this.activate}
      isActive={this.isActive}
      key={i}
    />
  );

  render() {
    const children = [Child1, Child2];

    return <div>{children.map(this.renderChild)}</div>;
  }
}
ReactDOM.render(<Root />, document.getElementById('root'))
&#13;
<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="root"></div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

好的,我找到了解决方案(原因)。此行为来自react-redux性能优化。我必须告诉react-redux来优化它,它会起作用。这个问题有点相关:

React componentDidUpdate method won't fire on inherited props change if connected to a store that didn't change