代码之家  ›  专栏  ›  技术社区  ›  Yomesh

何时根据redux的数据更新本地反应状态?

  •  1
  • Yomesh  · 技术社区  · 7 年前

    假设我的用例是打印帖子列表。我有以下反应成分。

    class App extends Component {
        constructor(props) {
            super(props);
            this.state = {
                loaded: !!(props.posts && props.posts.length)
            };
        }
    
        componentDidMount() {
            this.state.loaded ? null : this.props.fetchPosts();
        }
    
        render() {
            return (
                <ul>
                    {this.state.loaded
                        ? this.props.posts.length
                            ? this.props.posts.map((post, index) => {
                                    return <li key={index}>{post.title}</li>;
                              })
                            : 'No posts'
                        : 'Loading'}
                </ul>
            );
        }
    }
    

    fetchPosts 是一个操作,该操作通过API调用从DB获取post,然后用数据更新redux存储。现在,我的问题是

    1. 我应该什么时候根据道具更新我的本地反应状态?

    最初, this.props.posts 要么就是 undefined [] 所以 this.state.loaded 会是 false 我们将调用一个API来获取。一旦获取了数据,我是否应该将其更新为

    componentWillReceiveProps(nextProps) {
        this.setState({
            loaded: nextProps.posts && nextProps.posts.length
        });
    }
    

    这将设置本地状态和初始值 spinner/loader 将显示,然后 posts no posts . 然而,据我所知,React文档不鼓励 setState 在里面 componentWillReceiveProps 就像那样 lifecycle 在React 16中,钩子将被多次调用,并且也被弃用。

    那么,在哪个生命周期钩子中我应该更新本地状态?

    1. 只在Redux中维护加载机制会更好吗?

      class App extends Component {
          constructor(props) {
              super(props);
          }
      
          compomentDidMount() {
              this.props.loaded ? null : this.props.fetchPosts();
          }
      
          render() {
              return (
                  <ul>
                      {this.props.loaded
                          ? this.props.posts.length
                              ? this.props.posts.map((post, index) => {
                                      return <li key={index}>{post.title}</li>;
                              })
                              : 'No posts'
                          : 'Loading'}
                  </ul>
              );
          }
      }
      

    这里所有的东西都只在Redux商店维护。如果其他方法更好的话,我很想知道。谢谢!

    2 回复  |  直到 7 年前
        1
  •  4
  •   trixn    7 年前

    建议的解决方案是将其移动到 mapStateToProps . 大多数情况下,当你需要从你的商店获得数据时(这里是 posts )或从存储中派生的数据(此处 loading )那么 地图状态 是注射的正确地点。通常,让从存储中获取数据的组件尽可能哑是一个好主意。同时,将状态保存在从存储派生的组件中有点违反了单一真相来源原则,因为如果不注意,它可能会失去同步:

    class App extends Component {
        render() {
            const {loading, posts} = this.props;
    
            if (loading) return 'Loading';
    
            if (!posts.length) return 'No Posts';
    
            return (
                <ul>
                    {posts.map((post, index) => (
                        <li key={index}>{post.title}</li>;
                    ))}
                </ul>
            );
        }
    }
    
    const mapStateToProps = ({posts}) => ({
        posts
        loading: !posts,
    });
    
    export default connect(mapStateToProps, /* mapDispatchToProps */)(App);
    
        2
  •  3
  •   Harry Uglow    7 年前

    2是正确的。最好只在Redux中保持状态。否则,这个组件有两个独立的状态!