上一节我们学习了最基本的redux概念,但是这时会有一个问题,在实际的开发中我们要怎么使用呢?学习的终极目标是使用,光学不用假功夫, 我们这次就来看看redux和react实际项目的结合。
文件结构
通过上节的学习,我们知道redux有三大基本概念,action、reducers 、store缺一不可,那么怎样组织代码结构也就显而易见了, 我们在项目中创建一个单独的redux文件夹,其中包含action、reducers 、store:
sagas是之后学习到中间件时的知识,此处可以暂时不管,那你可能要问了,这里只看到了actions和reducers,store在哪里呢?
Store
其实他就是index.js,在该文件中我们只需要将reducers引入并放在createStore的第一个参数即可:
import {createStore} from "redux";
import reducers from "./reducers";
let store;
store = createStore(reducers);
export default store;
这样我们的store就创建好了。真正的store定义其实在每个reducers中就定义好了。
注意这里我们只是使用了最基本的方式去进行了创建,之后当引入中间件时我们还会对创建过程进行进一步的深化。
创建出store后就需要将store整个挂载在app上,这样你的整个app才能访问到Redux store中的数据:
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import store from "./store";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
Action
我们在具体的页面上可以使用react-redux提供的connect()帮助起来调用。
bindActionCreators() 可以自动把多个 action 创建函数 绑定到 dispatch() 方法上。
我们先来看一下connect方法,它接收两个参数,都是可选的:
- mapStateToProps:每当store state发生变化时,就被调用。接收整个store state,并且返回一个该组件所需要的数据对象
- mapDispatchToProps:这个参数可以是一个函数或对象
- 如果是一个函数,一旦该组件被创建,就会被调用。接收dispatch作为一个参数,并且返回一个能够使用dispatch来分发actions的若干函数组成的对象*
- 如果是一个action creators构成的对象,每一个action creator将会转化为一个prop function并会在调用时自动分发actions。注意: 我们建议使用这种形式。
通常我们可以这样去connect
@connect(
state => ({}),
dispatch => ({})
)
export default class App extends Component {
// ...
}
其中第一个参数中就可以写我们在这个页面中需要用到的所有store中数据,而第二个参数中就可以写我们这个页面中所有会被发起的actions。
@connect(
state => ({
num: state.numReducers.num // reducer中定义的state
}),
dispatch => ({
addNum: bindActioCreators(addNum,dispatch) // 创建出一个可以直接在页面中调用的dispatch(action)
})
)
这里的addNum就是我们需要在action中去定义的action创建函数。
// num加
export const addNum = (payload) => {
return {
type: 'num add',
payload
}
};
注意一般在大型的项目中因为actions会有很多,所以我们会将type的定义单独的放在一个actionType.js文件夹中,统一进行创建,这样方便后期维护。
Reducers
Reducers在项目中使用和基础的没有什么不同,需要在其中定义initState和一个纯函数对state和action进行计算,返回一个新的state。
需要注意的就是随我们的应用体积变大,我们应该将不同功能模块的reducers进行拆分提取,每个模块有自己的reducer,最后通过redux提供的
combineReducers()工具类将他们整合起来,将生成的对象放入store的createStore()中即可。