Reducer是用于改变数据的函数
1.一个数据仓库,有且仅有一个reducer,并且通常情况下,一个工程只有一个仓库,因此,一个系统,只有一个reducer
2.为了方便管理,通常会将reducer放到单独的文件中。
// src/redux/reducer/index.js
import * as actionTypes from './action/action-type';
/**
* reducer 本质上是一个普通函数
* @param {*} state 之前仓库中的状态(数据)
* @param {Object} action 要做什么,约定格式为 {type:"操作类型", payload:附加数据}
*/
export default function reducer(state, action) {
// 返回一个新的状态
if (action.type === actionTypes.INCREASE) {
return state + 1;
} else if (action.type === actionTypes.DECREASE) {
return state - 1;
} else if (action.type === actionTypes.SET) {
return action.payload;
} else {
// 如果是一个无效的操作类型,数据不变
return state;
}
}
// src/redux/index.js
import { createStore, bindActionCreators } from 'redux';
import * as numberActions from './action/number-action';
import reducer from './reducer';
// 初始值为10
const store = createStore(reducer, 10);
3.reducer被调用的时机
①.通过store.dispatch,分发了一个action,此时,会调用reducer
②.当创建一个store的时候,会调用一次reducer,主要是为了初始化
- 可以利用这一点,用reducer初始化状态
- 创建仓库时,不传递任何默认状态
- 将reducer的参数state设置一个默认值
// src/redux/reducer/index.js
import * as actionTypes from './action/action-type';
/**
* reducer 本质上是一个普通函数
* @param {*} state 之前仓库中的状态(数据)
* @param {Object} action 要做什么,约定格式为 {type:"操作类型", payload:附加数据}
*/
export default function reducer(state=10, action) {
// 返回一个新的状态
if (action.type === actionTypes.INCREASE) {
return state + 1;
} else if (action.type === actionTypes.DECREASE) {
return state - 1;
} else if (action.type === actionTypes.SET) {
return action.payload;
} else {
// 如果是一个无效的操作类型,数据不变
return state;
}
}
// src/redux/index.js
import { createStore, bindActionCreators } from 'redux';
import * as numberActions from './action/number-action';
import reducer from './reducer';
// 初始值为10
const store = createStore(reducer);
4.reducer内部通常使用switch来判断type值
// src/redux/reducer/index.js
import * as actionTypes from '../action/action-type';
/**
* reducer 本质上是一个普通函数
* @param {*} state 之前仓库中的状态(数据)
* @param {Object} action 要做什么,约定格式为 {type:"操作类型", payload:附加数据}
*/
export default function reducer(state = 10, action) {
console.log('reducer被调用了', state, action);
// 返回一个新的状态
switch (action.type) {
case actionTypes.INCREASE:
return state + 1;
case actionTypes.DECREASE:
return state - 1;
case actionTypes.SET:
return action.payload;
// 如果是一个无效的操作类型,数据不变
default:
return state;
}
}
5.reducer必须是一个没有副作用的纯函数
为什么需要是纯函数
a.纯函数有利于测试和调试
b.有利于还原数据
c.有利于将来与react结合时的优化
具体要求
a.不能改变参数,因此若要让状态变化,必须得到一个新的状态
b.不能有异步
c.不能对外部环境造成影响
import * as actionTypes from '../action/action-type';
/**
* reducer 本质上是一个普通函数
* @param {*} state 之前仓库中的状态(数据)
* @param {Object} action 要做什么,约定格式为 {type:"操作类型", payload:附加数据}
*/
export default function reducer(state = { name: 'jerry', age: 12 }, action) {
// state为对象时,返回一个新的状态
switch (action.type) {
case actionTypes.INCREASE:
return { ...state, age: state.age + 1 };
// return Object.assign({}, state, { age: state.age + 1 });
case actionTypes.DECREASE:
return state - 1;
case actionTypes.SET:
return action.payload;
// 如果是一个无效的操作类型,数据不变
default:
return state;
}
}
6.由于在大中型项目中,操作比较复杂,数据结构也比较复杂,因此,需要对reducer进行细分。
①.redux提供了方法,可以帮助我们更加方便的合并reducer(vscode快捷创建reducer方式:rxreducer)
//src/redux/reducer/loginUser.js
import { SET_LOGIN_USER_TYPE } from '../action/loginuser-action';
const initialState = null;
// 当前登录用户的reducer
export default (state = initialState, { type, payload }) => {
switch (type) {
case SET_LOGIN_USER_TYPE:
return payload;
default:
return state;
}
};
//src/redux/reducer/users.js
import * as usersAction from '../action/users-action';
import uuid from 'uuid';
const initialState = [
{ id: uuid(), name: '用户1', age: 11 },
{ id: uuid(), name: '用户2', age: 12 },
];
// 所有登录用户的reducer
export default (state = initialState, { type, payload }) => {
switch (type) {
case usersAction.ADD_USER:
return [...state, payload];
case usersAction.DELETE_USER:
return state.filter((user) => user.id !== payload.id);
case usersAction.UPDATE_USER:
// id存在则替换成payload对象,否则的话用原来的对象
return state.map((user) => (user.id === payload.id ? {...user, ...payload} : user));
default:
return state;
}
};
// src/redux/reducer/index.js
import loginUserReducer from './loginUser';
import usersReducer from './users';
export default (state = {}, action) => {
// 将不同的reducer合并到一处进行管理
const newState = {
loginUser: loginUserReducer(state.loginUser, action),
users: usersReducer(state.users, action),
};
return newState;
};
②.combineReducers: 合并reducer,得到一个新的reducer,该新的reducer管理一个对象,该对象中的每一个属性交给对应的reducer管理。
import loginUserReducer from './loginUser';
import usersReducer from './users';
import { combineReducers } from 'redux';
// export default (state = {}, action) => {
// const newState = {
// loginUser: loginUserReducer(state.loginUser, action),
// users: usersReducer(state.users, action),
// };
// return newState;
// };
// 相当于 5-11 行的代码
export default combineReducers({
loginUser: loginUserReducer,
users: usersReducer,
});