【问题标题】:How to pass redux state to sub routes?如何将 redux 状态传递给子路由?
【发布时间】:2016-01-19 01:46:58
【问题描述】:

我很难理解如何将 redux 与 react-router 一起使用。

index.js

[...]

// Map Redux state to component props
function mapStateToProps(state)  {
  return {
    cards: state.cards
  };
}

// Connected Component:
let ReduxApp = connect(mapStateToProps)(App);

const routes = <Route component={ReduxApp}>
  <Route path="/" component={Start}></Route>
  <Route path="/show" component={Show}></Route>
</Route>;

ReactDOM.render(
  <Provider store={store}>
    <Router>{routes}</Router>
  </Provider>,
  document.getElementById('root')
);

App.js

import React, { Component } from 'react';

export default class App extends React.Component {
  render() {
    const { children } = this.props;
    return (
      <div>
      Wrapper
        {children}
      </div>
    );
  }
}

显示.js

import React, { Component } from 'react';

export default class Show extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <ul>
        {this.props.cards.map(card => 
          <li>{card}</li>
        )}
      </ul>
    );
  }
}

这会抛出

未捕获的类型错误:无法读取未定义的属性“地图”

我发现的唯一解决方案是使用它而不是 {children}:

{this.props.children &&
 React.cloneElement(this.props.children, { ...this.props })}

这真的是正确的做法吗?

【问题讨论】:

    标签: javascript reactjs react-router redux


    【解决方案1】:

    我通过在每个组件中使用 connect 显式映射状态来解决它:

    export default connect(function selector(state) {
      return {
        cards: state.cards
      };
    })(Show);
    

    这样我可以决定组件应该访问哪些状态属性,从而减少对 props 的污染。不过不确定这是否是最佳做法。

    【讨论】:

    • 我认为您不需要在每个组件中都这样做,只需您的顶级和路由处理程序组件即可。在您的示例中, Show 是一个路由处理程序,因此使用 connect 完全没问题(这就是所谓的智能或容器组件)。它下面的所有组件(Presentational 或哑组件)都应该从 Smart 组件获取它们的状态作为 props。看看这里:redux.js.org/docs/basics/UsageWithReact.html
    • 您能否举一些简单的例子说明如何正确执行此操作?
    【解决方案2】:

    使用 react-redux

    为了将任何状态或动作创建者注入 React 组件的 props,您可以使用 react-redux 中的 connect,这是 Redux 的官方 React 绑定。​​

    值得查看connect here 的文档。

    作为基于问题中指定内容的示例,您将执行以下操作:

    import React, { Component } from 'react';
    // import required function from react-redux
    import { connect } from 'react-redux';
    
    // do not export this class yet
    class Show extends React.Component {
      // no need to define constructor as it does nothing different from super class
    
      render() {
        return (
          <ul>
            {this.props.cards.map(card => 
              <li>{card}</li>
            )}
          </ul>
        );
      }
    }
    
    // export connect-ed Show Component and inject state.cards into its props.
    export default connect(state => ({ cards: state.cards }))(Show);
    

    为了让它工作,尽管你必须用来自react-reduxProvider 包装你的根组件或路由器(这已经存在于上面的示例中)。但为了清楚起见:

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { Router, Route } from 'react-router';
    
    import { createStore } from 'redux';
    import { Provider } from 'react-redux';
    
    import reducers from './some/path/to/reducers';
    
    const store = createStore(reducers);
    
    const routes = <Route component={ReduxApp}>
      <Route path="/" component={Start}></Route>
      <Route path="/show" component={Show}></Route>
    </Route>;
    
    ReactDOM.render(
      // Either wrap your routing, or your root component with the Provider so that calls to connect have access to your application's state
      <Provider store={store}>
        <Router>{routes}</Router>
      </Provider>,
      document.getElementById('root')
    );
    

    如果任何组件不需要注入任何状态或动作创建者,那么您可以只导出一个“哑”的 React 组件,并且您的应用程序的任何状态都不会在渲染时暴露给组件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-03
      • 2019-02-17
      • 2020-10-29
      • 1970-01-01
      • 1970-01-01
      • 2017-01-26
      • 2016-10-28
      • 2018-12-14
      相关资源
      最近更新 更多