在redux状态更新后没有调用ComponentDidMount?

时间:2018-02-11 16:53:46

标签: reactjs redux react-redux react-lifecycle

我想我在这里错过了一个关于React和Redux的概念。我正在尝试使用存储在redux中的对象,我遇到了麻烦。

REDUX: 我有一个动作fetchItems,它从数据库中获取所有项目。此操作成功。

REACT: 我有一个容器UserProfile,它调用componentDidMount中的fetchItems。

class UserProfile extends Component {

  componentWillMount() {
    console.log('------------ USER PROFILE -------------------');
  }

  componentDidMount() {
    console.log('[ComponentDidMount]: Items: ', this.props.items);
    this.props.fetchItems();
  }

  render() {
    let profile = null;
    console.log('[Render]: Items: ', this.props.items);

    return <Auxillary>{profile}</Auxillary>;
  }
}

const mapStateToProps = state => {
  return {
    items: state.items.items
  };
};

const mapDispatchToProps = dispatch => {
  return {
    fetchItems: () => dispatch(actions.fetchItems())
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(UserProfile);

我看到的问题是this.props.items始终为null(即使fetchItems成功)。我可以检测到项目存储在redux存储中的唯一方法是使用componentWillRecieveProps(nextProps)。在这里,我成功地看到了nextProps中的项目。我觉得使用componentWillReceiveProps可能太“混乱”了。我想我要问的是,在react中处理redux状态更新的标准方法是什么?

Aseel

4 个答案:

答案 0 :(得分:2)

在反应中,我们有一种叫做国家的东西。如果更改了组件的状态,则组件将重新呈现。说过我们可以在this.setState()内使用componentWillRecieveProps来更新状态,而状态又会重新呈现组件。所以你的代码看起来像这样,这是处理反应中Redux级别状态变化的标准方法。

class UserProfile extends Component {

    constructor(props) {
        super(props);
        this.state = {
            items: props.items
        }
    }
    componentWillMount() {
      console.log('------------ USER PROFILE -------------------');
    }

    componentWillRecieveProps({ items }) {
        this.setState({ items });
    }

    componentDidMount() {
      console.log('[ComponentDidMount]: Items: ', this.state.items);
      this.props.fetchItems();
    }

    render() {
      let profile = null;
      console.log('[Render]: Items: ', this.state.items);

      return <Auxillary>{profile}</Auxillary>;
    }
  }

  const mapStateToProps = state => {
    return {
      items: state.items.items
    };
  };

  const mapDispatchToProps = dispatch => {
    return {
      fetchItems: () => dispatch(actions.fetchItems())
    };
  };

  export default connect(mapStateToProps, mapDispatchToProps)(UserProfile);

P.S只是在componentWillMount内进行API调用也无济于事,因为API调用是异步的,并且可能需要一些时间来解决,直到那时反应将完成渲染组件。所以你仍然必须使用componentWillRecieveProps

答案 1 :(得分:1)

标准做法是在构造函数或componentWillMount()中调用this.props.fetchItems()。

在渲染后调用componentDidMount,这就是你的项目不呈现的原因 - 它们在初始渲染之后才存在。

答案 2 :(得分:1)

周期将是:

  • constructor()
  • componentWillMount()(将很快弃用:https://medium.com/@baphemot/whats-new-in-react-16-3-d2c9b7b6193b
  • render() =&gt;第一个渲染(this.props.items,来自mapStateToProps将是未定义的)
  • componentDidMount() =&gt;启动fetchItems() =&gt;改变redux state =&gt;改变this.props.items =&gt;启动将设置render()的第二个this.props.items

所以:

  • 你应该有两个console.log('[Render]: Items: ', this.props.items);
  • 你应该处理一个&#34; loading&#34;当this.props.items为null时的状态

如果第二个console.log仍为null,请尝试在reducer中添加logState,在mapStateToProps中,...也许它不是state.items.items ...

答案 3 :(得分:0)

您可以通过某些方式解决此问题。 第一次调用render()时,它通过redux connect方法订阅了在redux存储中初始化的初始props / state。在您的情况下, null 。 始终使用一些有意义的数据初始化您的redux商店。

在您的情况下,如果是数组,您可以使用空数组初始化。 当您发送操作时,您的商店会更新,订阅商品的组件将会重新呈现,这样您就不必在 componentWillReceiveProps中使用 setState ,您可以避免使用它。

你需要在渲染中处理某些情况,比如数组是空的并且数据仍在加载然后显示某种加载器并且一旦获取数据然后显示它。