【问题标题】:Rerendering React components after redux state's locale has updated在 redux state 的 locale 更新后重新渲染 React 组件
【发布时间】:2016-10-29 17:28:56
【问题描述】:

我在React 应用程序中实现了Redux,到目前为止效果很好,但我有一个小问题。

我的导航栏中有一个选项可以更改存储在redux's state 中的locale。当我更改它时,我希望每个组件都重新渲染以更改转导。为此,我必须指定

locale: state.locale

mapStateToProps函数中...导致大量代码重复。

有没有办法将语言环境隐式传递到 connected 和 react-redux 的每个组件的 props 中?

提前致谢!

【问题讨论】:

    标签: reactjs redux react-redux react-intl


    【解决方案1】:

    Redux 实现了一个 shouldComponentUpdate 来防止组件更新,除非它的 props 被改变。

    在您的情况下,您可以通过将pure=false 传递给connect 来忽略此检查:

    connect(select, undefined, undefined, { pure: false })(NavBar);
    

    出于性能原因,这是一件好事,但可能不是您想要的。

    相反,我建议编写一个自定义连接函数,以确保始终将locale 添加到您的组件道具中:

    const localeConnect = (select, ...connectArgs) => {
      return connect((state, ownProps) => {
        return {
          ...select(state, ownProps),
          locale: state.locale
        };
      }, ...connectArgs);
    };
    
    // Simply use `localeConnect` where you would normally use `connect`
    const select = (state) => ({ someState: state.someState });
    
    localeConnect(select)(NavBar);  // props = { someState, locale }
    

    【讨论】:

    • 这正是我的想法,但无法找到重写连接函数的方法......非常感谢!
    • 您好,您确定您给我的代码管理 ownProps 吗?在我的代码中的某些地方,我将 connect 替换为 localeConnect,但有时 ownProps 未定义,当我再次使用 connect 并在 mapStateToProps 中指定区域设置以使其工作时,它不是......提前致谢!
    • 抱歉,我之前没有在 select 中使用带有 props 的 redux(一些必读的内容让我填满了!)。似乎使用扩展运算符在第一次渲染上起作用,但不是在第二次渲染上。我只指定stateownProps 进行了测试,这似乎有效。更新了代码,希望对你也有用!
    • 你好,它现在就像一个魅力,再次非常感谢!
    【解决方案2】:

    为了减少代码的重复,我通常只是在将状态映射到 props 时将箭头函数传递给 connect 方法,这对我来说看起来更简洁。不幸的是,我认为没有其他方法可以使其隐含,因为您的组件可以订阅多个商店“对象”。

    export default connect((state) => ({
      local: state.locale
    }))(component);
    

    【讨论】:

      【解决方案3】:

      为了解决这个问题,你可以设置你父组件的Context,并在你的子组件中使用它。这是 Redux 用来将 store 的 statedispatch 函数提供给连接的 React 组件。

      在您的 Parent 组件中,实现 getChildContext 并指定每个变量的 PropType

      class Parent extends React.Component {
          getChildContext() {
              return {
                  test: 'foo'
              };
          }
      
          render() {
              return (
                  <div>
                      <Child />
                      <Child />
                  </div>
              );
          }
      
      }
      
      Parent.childContextTypes = {
          test: React.PropTypes.string
      };
      

      在您的子组件中,使用this.context.test 并指定其PropType

      class Child extends React.Component {
          render() {
              return (
                  <div>
                      <span>Child - Context: {this.context.test}</span>
                  </div>
              );
          }
      }
      
      Child.contextTypes = {
          test: React.PropTypes.string
      };
      

      这是一个 demo 的工作。

      我不妨提一下,虽然 Redux 等库使用此功能,但 React 的文档指出这是一个高级和实验性功能,可能会在未来的版本中更改/删除。我个人不推荐这种方法,而是像您最初提到的那样简单地在 mapStateToProps 中传递您需要的信息。

      【讨论】:

      • 您好,感谢您的回答。我知道这种可能性,但它涉及更多的代码重复,并不能真正解决我必须将变量显式传递给我的每个组件的事实......无论如何,谢谢!
      • 我不确定我是否听懂了您所说的 - 我发布的示例表明您不必使用 React 的 Context 功能显式地将变量传递给子组件。在我的父组件的render 函数中,子组件在没有道具的情况下被渲染 - 假设父组件的任何子组件都将隐式访问上下文。
      • 是的,但是您必须为每个希望将上下文传递给道具的子组件编写ChildrenComponent.contextTypes = { test: React.PropTypes.string };...这与在mapStateToProps中指定它相同
      猜你喜欢
      • 1970-01-01
      • 2018-03-24
      • 1970-01-01
      • 2018-06-15
      • 2017-06-17
      • 1970-01-01
      • 2018-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多