3

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

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

反应:我有一个容器 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 始终为空(即使 fetchItems 成功)。我可以检测到项目存储在 redux 存储中的唯一方法是使用 componentWillRecieveProps(nextProps)。在这里,我成功看到了 nextProps 中的项目。我觉得使用 componentWillReceiveProps 可能太“杂乱”了。我想我要问的是,在反应中处理 redux 状态更新的标准方法是什么?

阿塞尔

4

4 回答 4

3

循环将是:

  • constructor()
  • componentWillMount()(顺便说一句,很快就会被弃用:https ://medium.com/@baphemot/whats-new-in-react-16-3-d2c9b7b6193b )
  • render()=> 首次渲染 ( this.props.items,来自 mapStateToProps 将是未定义的)
  • componentDidMount()=> 启动fetchItems()=> 更改 redux 状态 => 更改 this.props.items => 启动将设置的第二个render()位置。this.props.items

所以 :

  • 你应该有两个console.log('[Render]: Items: ', this.props.items);
  • 当 this.props.items 为空时,您应该处理“加载”状态

如果第二个 console.log 仍然为空,请尝试在您的减速器中添加日志,在 mapStateToProps 中,......也许它不是 state.items.items ...

于 2018-02-11T18:22:29.557 回答
2

在反应中,我们有一种叫做状态的东西。如果组件的状态发生更改,则组件将重新渲染。话虽如此,我们可以使用this.setState()insidecomponentWillRecieveProps来更新状态,这反过来又会重新渲染组件。所以你的代码看起来像这样,这是在 react 中处理 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);

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

于 2018-02-11T19:45:12.497 回答
1

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

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

于 2018-02-11T17:10:56.630 回答
0

有一些方法可以解决这个问题。第一次调用 render() 时,它订阅了通过 redux connect 方法在 redux store 中初始化的初始 props/state。在你的情况下itemsnull。总是用一些有意义的数据初始化你的 redux 存储。

在您的情况下,如果项目将是数组,您可以使用空数组进行初始化。当您调度操作时,您的商店将得到更新,并且订阅项目的组件将被重新呈现,这样您就不必在componentWillReceiveProps中使用setState并且可以避免使用它。

您需要在渲染中处理某些情况,例如如果数组为空且数据仍在加载,然后显示某种加载器,一旦获取数据然后显示它。

于 2018-02-12T18:05:35.607 回答