背景: 在react中使用redux
重点:不要滥用redux,如果你的页面非常简单,没有 那么多的互动,那么就不要使用redux,反而会增加项目的复杂性。
如果你有以下情况,则可以考虑使用redux:
- 某个组件的状态,需要共享
- 某个状态需要在任何地方都可以拿到
- 一个组件需要改变全局状态
- 一个组件需要改变另一个组件的状态
store 一个保存数据的容器,只能有一个store。
redux提供 createStore 可以生成store。
// store/index.js import { createStore, applyMiddleware, compose } from 'redux' import logger from 'redux-logger' import reducers from '../reducers/index' const middlewares = [] middlewares.push(logger) const store = createStore( // 将reducer传入,就可以自动调用reducer了 reducers, compose( applyMiddleware(...middlewares) ) ) export default store
action 是一个对象{type: string, data: someData}。
发布一个action,只有store.dispatch()一个方法,联合起来就是这样:
import store from '../store/index' store.dispatch({ type: 'ADD_TODO', payload: 'Learn Redux' });
实际使用例子:
// 把上面创建的store引进了,需要使用store.dispatch import store from '../store/index' export const CHANGE_DATABASE = 'CHANGE_DATABASE' export const DATA_BASE = 'DATA_BASE' /** * 如果有需要异步请求数据的,也可以放在这里, 比如第三个fetchfavoritesTable方法 */ export const changeDataBase = (data) => { const dispatch = store.dispatch dispatch({ type: CHANGE_DATABASE, data: data }) } export const saveDataBase = (data) => { store.dispatch({ type: DATA_BASE, data: data }) } export const fetchFavoritesTable = (pageSize, current) => { const dispatch = store.dispatch return get(adhocFetchUrl.favorites_get, { page: current, pageSize }) .then((res) => { if (res.status === 200) { const result = res.data const data = [] for (let i = 0, length = result.length; i < length; i++) { data.push({ key: i, id: result[i].id, content: result[i].content, createTime: result[i].createTime, name: result[i].name }) } const finialData = { data: data, total: res.pageCount } dispatch({ type: FAVORITES_DATA, data: finialData }) } else { console.warn('请求搜索历史error:', res) } }) }
reducer store收到一个action后,必须给出一个新的state,这样view才会变化,这个计算过程,叫做reducer
reducer是一个函数,接受action和当前state为参数:
const reducer = function (state, action) { // ... return new_state; };
dispatch一个action之后,会自动触发reducer,那么这个前提就是需要在creatStore时候,讲reducer作为参数传入。
拆分reducer:
// 这是其中一个reducer文件: a.js export default (state = init, actions) => { const { type, data } = actions switch (type) { case CHANGE_DATABASE: return { ...state, database: data } case CHANGE_TABLE_ID: return { ...state, tableId: data }default: return state } }
合并reducer 使用redux提供的combineReducers
import { combineReducers } from 'redux' import home from './a' import other from './b' export default combineReducers({ home, other })
这样就可以做到,一个模块对应一个reducer 和一个action文件
目录如下图: