也许我并没有将我的头放在 redux 上,但是我看到的所有示例都没有真正在容器之间访问太多状态,所以我没有看到 store.getState() 的太多用法,但即使你想派送,您需要访问商店,对吗?
因此,除了从“路径/到/商店/商店”导入导入商店
在我想要 getState() 或“调度”的每个文件中,我如何访问该状态,因为如果我不包含它,则存储未定义。
也许我并没有将我的头放在 redux 上,但是我看到的所有示例都没有真正在容器之间访问太多状态,所以我没有看到 store.getState() 的太多用法,但即使你想派送,您需要访问商店,对吗?
因此,除了从“路径/到/商店/商店”导入导入商店
在我想要 getState() 或“调度”的每个文件中,我如何访问该状态,因为如果我不包含它,则存储未定义。
通常,您只想制作可以访问 store 的顶级容器组件 - 它们会将任何必要的数据或动作分派作为props传递给它们的子组件。这是“智能”和“哑”组件之间的区别——“智能”组件知道 Redux 存储/状态,而“哑”组件只是将 props 传递给它们,而对更大的应用程序状态一无所知。
然而,即使只是将 store 传递给容器组件也会变得乏味。这就是 React-Redux 提供一个开箱即用的组件来包装整个应用程序的原因。在文档中查看。这是Provider
组件,当您用它包装整个应用程序时,您只需将 store 传递给组件一次:
import createStore from '../store';
const store = createStore()
class App extends Component {
render() {
return (
<Provider store={store}>
<MainAppContainer />
</Provider>
)
}
}
正如你在这里看到的,我有一个单独的配置文件,只用于我的商店,因为你可以做很多修改,对于任何远程复杂的应用程序,你会发现自己对使用compose应用中间件等事情做同样的事情。
然后,您剩余的任何“智能”组件(通常是包装器)都需要监听 store。这是使用连接方法完成的。这允许您将状态的各个部分映射到您的组件属性,以及将操作作为属性进行调度。
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
被传递给 dispatch action as getSomething
,在 myonClick
我可以调用this.props.getSomething
并且它将调用 dispatch action而不需要任何对 store 的访问。以同样的方式,它可以继续向下传递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'
}
}
}
此操作类型是您的减速器将侦听以了解正在触发哪个操作的类型。
如果你使用这个react-redux
包,你最终会Provider
用一个store
prop将你的组件包裹在 a 中。这会在 React 上下文中设置您的单个存储,然后可以从connect
子组件中的方法访问它。该connect
方法采用两个函数(mapStateToProps 和 mapDispatchToProps),它们是用于从存储中获取状态和分派消息的钩子。
使用 mapStateToProps React 组件:
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(所有减速器组合)
import getProduct from './products';
import getReviews from './reviews';
import { combineReducers } from 'redux';
const allReducers = combineReducers({
cartReducer, getProduct, getReviews
})
export default allReducers;
动作(动作/index.js)
// console.log('hahahahah')
return {
type: 'ADD_PRODUCT',
payload: n
}
}