next.js mapStateToProps、mapDispatchToProps 和 getInitialProps

Posted

技术标签:

【中文标题】next.js mapStateToProps、mapDispatchToProps 和 getInitialProps【英文标题】:next.js mapStateToProps, mapDispatchToProps and getInitialProps 【发布时间】:2019-03-01 11:06:54 【问题描述】:

在使用 next.js 时,我目前仍在尝试围绕 redux 进行思考,但我不确定将 redux 与 next.js 一起使用的最佳方式是什么。我习惯于将 mapDispatchToProps 用于我的操作,并将 mapStateToProps 用于我的道具。经过一些研究,我现在在我的 _app.js 中使用 next-redux-wrapper,就像推荐的那样,但现在我正在努力解决如何最好地获取我的道具并调度我的动作。我查看了一些示例和实践,现在有一个基于这些示例之一的计数器组件。

class Counter extends Component 
  increment = () => 
    const dispatch = this.props
    dispatch(incrementCount())
  

  decrement = () => 
    const dispatch = this.props
    dispatch(decrementCount())
  

  reset = () => 
    const dispatch = this.props
    dispatch(resetCount())
  

  render () 
    const  count  = this.props
    return (
      <div>
        <h1>Count: <span>count</span></h1>
        <button onClick=this.increment>+1</button>
        <button onClick=this.decrement>-1</button>
        <button onClick=this.reset>Reset</button>
      </div>
    )
  


function mapStateToProps (state) 
  const count = state.counter;
  return count;


export default connect(mapStateToProps)(Counter)

到目前为止,我看到的大多数示例都执行与此类似的操作,或者仅在 getInitialProps 中调度操作。是否有理由这样做而不使用 mapDispatchToProps?

因为这项工作也很好:

export default connect(null, authenticate)(Signin);

在 getIntialProps 中调度动作似乎有一些缺点(或者我犯了一些错误),因为当道具改变时它们不会再次被执行。在我的用户配置文件组件中,我根据来自 redux 商店的令牌获取当前用户,如下所示:

const Whoami = (isAuthenticated, user) => (
  <Layout title="Who Am I">
    (isAuthenticated && user && <h3 className="title is-3">You are logged in as <strong className="is-size-2 has-text-primary">user</strong>.</h3>) ||
      <h3 className="title is-3 has-text-danger ">You are not authenticated.</h3>
  </Layout>
);

Whoami.getInitialProps = async function (ctx) 
  initialize(ctx);

  const token = ctx.store.getState().auth.token;
  if(token) 
    const response = await axios.get(`$API/user`, headers: 
      authorization: token
    );
    const user = response.data.user;
    return 
      user
    ;
  
    

const mapStateToProps = (state) => (
  isAuthenticated: !!state.auth.token
);

export default connect(mapStateToProps)(Whoami);

这对于初始页面加载或在客户端导航时非常有效,但是当令牌过期或我注销时,如果没有重新加载或在没有我的 mapStateToProps 的情况下再次导航,页面不会反映这一点。但是将关注点拆分为 2 个单独的功能似乎非常笨拙。但我找不到更清洁的方法。

提前致谢

【问题讨论】:

【参考方案1】:

在玩了 next 之后,我找到了一些问题的答案。对于初始加载后数据未更改的页面,我可以通过重写我的 thunk 来摆脱 mapStateToProps 以返回调度,并且只使用 getInitialProps 像这样:

export function fetchShow(id) 
  return (dispatch) => 
      dispatch( type: actionTypes.FETCH_SHOW_REQUESTED,id);
      // we need to return the fetch so we can await it
      return fetch(`http://api.tvmaze.com/shows/$id`)
          .then((response) => 
              if (!response.ok) 
                  throw Error(response.statusText);
              
              //dispatch(itemsIsLoading(false));
              return response;
          )
          .then((response) => response.json())
          .then((data) =>      dispatch(type: actionTypes.FETCH_SHOW_SUCEEDED,id, show: data, time: Date.now() ))
          .catch(() => dispatch( type: actionTypes.FETCH_SHOW_ERROR,id ));
  ;


Post.getInitialProps = async function (store, isServer, pathname, query) 
  const  id  = query;
  const show = await store.dispatch(fetchShow(id));
  return show;

对于在商店更改时数据应该更新的页面,我还不确定。我目前的想法是尝试编写一个辅助函数,该函数将从 getInitialProps 和 mapStateToProps 调用以减少代码重复,但我还不确定。

【讨论】:

【参考方案2】:

关于mapDispatchToProps

最好使用mapDispatchToProps,至少因为它更容易测试:你可以只传递一个模拟函数给你的组件。使用this.props.dispatch 调度一些导入的操作可能会更加困难。

关于getInitialProps

This answer 可能会有所帮助:

GetInitialProps: 由 Next.js 提供,它并不总是被触发,所以要小心,当你将一个组件包装在另一个组件中时会发生这种情况。如果父 Component 有 GetInitialProps,则永远不会触发子组件的 GetInitialProps,请参阅this thread 了解更多信息。

【讨论】:

好的,谢谢,所以正常使用 mapDispatchToProps 没有任何问题,很高兴知道。关于 GetInitialProps:您有什么想法可以更简洁地处理身份验证用例吗?据我了解,使用它的全部原因是它在客户端和服务器上都运行

以上是关于next.js mapStateToProps、mapDispatchToProps 和 getInitialProps的主要内容,如果未能解决你的问题,请参考以下文章

如何在 next.js 中使用带有样式组件主题的 window.matchMedia?

如何在 Next JS 中使用链接测试路由?

mapStateToProps 将数据传递给道具

如何访问 mapDispatchToProps 中 mapStateToProps 添加的属性?

在 mapStateToProps 中未定义 Redux 状态

Redux 应用程序嵌套状态中的 mapStateToProps() 状态?