也许我并没有围绕redux,但我见过的所有例子都没有真正访问容器之间的状态太多,所以我没有看到很多用于store.getState()的东西,但即使你想派遣,你需要访问商店,对吗?
所以,除了导入 从'path / to / store / store'
导入商店在我想要getState()或“dispatch”的每个文件中,如何访问该状态,因为如果我不包含它,则存储未定义。
答案 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),它们是从商店获取状态和调度消息的钩子。
答案 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
}
}