Redux,如果我想访问数据,是否必须在我的所有容器中导入商店?

时间:2016-02-09 19:18:36

标签: reactjs redux

也许我并没有围绕redux,但我见过的所有例子都没有真正访问容器之间的状态太多,所以我没有看到很多用于store.getState()的东西,但即使你想派遣,你需要访问商店,对吗?

所以,除了导入 从'path / to / store / store'

导入商店

在我想要getState()或“dispatch”的每个文件中,如何访问该状态,因为如果我不包含它,则存储未定义。

3 个答案:

答案 0 :(得分:76)

通常,您只想制作能够访问商店的顶级容器组件 - 它们会将任何必要的数据或操作调度作为道具传递给其子组件。这是“智能”和“哑”组件之间的区别 - “智能”组件了解Redux存储/状态,而“哑”组件只是将道具传递给他们并且不知道更大的应用程序状态。 / p>

然而,即使只是将商店传递给容器组件也会变得单调乏味。这就是为什么React-Redux提供了一个包装整个应用程序的开箱即用的组件。文档中Check it out。这是Provider组件,当您用它包装整个应用程序时,您只能将商店传递给组件一次

import createStore from '../store';

const store = createStore()

class App extends Component {

  render() {
    return (
      <Provider store={store}>
        <MainAppContainer />
      </Provider>
    )
  }
}

正如你在这里看到的,我有一个单独的配置文件只是为了我的商店,因为你可以做很多修改,对于任何远程复杂的应用程序,你会发现自己做同样的事情,比如使用{{ 3}}应用中间件。

然后,任何剩余的“智能”组件(通常是包装器)都需要收听商店。这是使用compose方法完成的。这允许您将状态的各个部分映射到组件属性,以及将操作作为属性分派。

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actionCreators from './actionCreators';

const mapStateToProps = function(state){
  return {
    something: state.something,
  }
}

const mapDispatchToProps = function (dispatch) {
  return bindActionCreators({
    getSomething: actionCreators.getSomething,
  }, dispatch)
}

class MainAppContainer extends Component {

    componentDidMount() {
      //now has access to data like this.props.something, which is from store
      //now has access to dispatch actions like this.props.getSomething
    }

    render() {
        //will pass down store data and dispatch actions to child components
        return (
               <div>
                   <ChildComponent1 something={this.props.something} />
                   <ChildComponent2 getSomething={this.props.getSomething} />
               </div>
        )
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(MainAppContainer)

由于您始终将调度操作和数据作为属性传递给子组件,因此您只需使用this.props引用该组件上的那些操作和数据。

基于上面的示例,您会看到,因为我将this.props.something传递给ChildComponent1,它可以访问商店中的something数据,但它无法访问getSomething派遣行动。同样,ChildComponent2只能访问getSomething调度操作,但不能访问something数据。这意味着您只能将组件暴露给他们所需的商店。

例如,由于ChildComponent2已作为getSomething传递给调度操作,因此在我的onClick我可以致电this.props.getSomething,它会调用调度操作无需任何访问商店。以同样的方式,它可以继续将getSomething传递给另一个子组件,该组件可以调用它和/或将其传递下去,并且循环可以无限期地继续。

class ChildComponent2 extends Component {

    render() {
        return (
            <div>
                <div onClick={this.props.getSomething}>Click me</div>
                <NestedComponent getSomething={this.props.getSomething} />
            </div>
        )
    }
}

根据评论进行修改

虽然这与问题没有直接关系,但在评论中你似乎对行动感到有些困惑。我实际上没有在这里定义动作getSomething。相反,在Redux应用程序中通常会将所有操作定义放在名为actionCreators.js的单独文件中。这包含与您的操作命名相同的函数,并返回具有type属性的对象以及操作所需的任何其他方法/数据。例如,这是一个非常简单的示例actionCreators.js文件:

export function getSomething() {
    return {
        type: 'GET_SOMETHING',
        payload: {
            something: 'Here is some data'
        }
    }
}

此操作类型是您的reducer将听取的内容,以了解正在触发的操作。

答案 1 :(得分:14)

如果您使用react-redux软件包,则最终会将您的组件包装在Provider的{​​{1}}道具中。这将在React上下文中设置您的单个存储,然后从子组件中的store方法访问该上下文。 connect方法有两个函数(mapStateToProps和mapDispatchToProps),它们是从商店获取状态和调度消息的钩子。

Take a look here for more information

答案 2 :(得分:0)

与mapStateToProps 反应组件:

import Item from './Item.jsx';
import { createStore } from 'redux';
import { getProduct, addProduct } from '../../actions';
import { connect } from "react-redux";

class Bundles extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    var productData = this.props.productData
    return (
      <div>
        <span>
          {
            productData.map(item => (
              <Item item={item} key={item.id} />
            ))
          }

        </span>
      </div >
    )
  }
}

const mapStateToProps = (state) => {
  // console.log(state.getProduct)
  return {
    productData: state.getProduct,
  };
};

export default connect(mapStateToProps)(Bundles);

产品减速器


const productReducer = (state = data, action) => {
  switch (action.type) {
    case "GET_PRODUCT":
      console.log(state)
      return state
    default:
      return state;
  }
}

export default productReducer;

RootReducer(所有的reducer合并)

import getProduct from './products';
import getReviews from './reviews';

import { combineReducers } from 'redux';

const allReducers = combineReducers({
  cartReducer, getProduct, getReviews
})

export default allReducers;

操作(action / index.js)

      // console.log('hahahahah')
      return {
        type: 'ADD_PRODUCT',
        payload: n
      }
    }