1,特点
用于改变数据仓库 store
数据的函数。
一个数据仓库,有且仅有一个 reducer
。而通常情况下,一个工程只有一个仓库,所以也只有一个 reducer
。
1.1,调用时机
- 当创建
store
时,会调用一次,可利用这点来初始化状态。 - 通过
store.dispatch
分发action
时,也会调用。
1.2,必须是纯函数
- 有利于测试和调试。
- 有利于还原数据。
- 有利于和 React 结合时做优化。
2,举例
目录
action
-- userAction.js
-- loginAction.js
reducer
-- user.js
-- login.js
-- index.js
-- index.js
通常
action
和reducer
中相同模块,命名也会相同。
2.1,action
// action/userAction.js
export const ADD_USER = Symbol("add_user");
export const DELETE_USER = Symbol("delete_user");
export const UPDATE_USER = Symbol("update_user");
export const createAddUserAction = (user) => ({
type: ADD_USER,
payload: user,
});
export const createDeleteUserAction = (id) => ({
type: DELETE_USER,
payload: id,
});
export const createUpdateUserAction = (id, newValue) => ({
type: UPDATE_USER,
payload: {
...newValue,
id,
},
});
// action/loginAction.js
export const LOGIN = Symbol("login");
export const createLoginAction = (user) => ({
type: LOGIN,
payload: user,
});
2.2,reducer
大型项目中,数据和操作都比较复杂。会对 reducer
进行细分方便管理。
// reducer/user.js
import { ADD_USER, DELETE_USER, UPDATE_USER } from "../action/userAction";
const initState = [
{ id: 1, name: "name1", age: 18 },
{ id: 2, name: "name2", age: 19 },
];
export default (state = initState, { type, payload }) => {
switch (type) {
case ADD_USER:
return [...state, payload];
case DELETE_USER:
return state.filter((f) => f.id !== payload);
case UPDATE_USER:
return state.map((m) => (m.id === payload.id ? { ...m, ...payload } : m));
default:
return state;
}
};
// reducer/login.js
import { LOGIN } from "../action/loginAction";
const initState = null;
export default (state = initState, { type, payload }) => {
switch (type) {
case LOGIN:
return payload;
default:
return state;
}
};
2.2.1,结合
而最终只有一个 reducer
,会在创建 store
时传递。
// reducer/index.js
import loginReducer from "./login";
import userReducer from "./user";
export default (state = {}, action) => {
const newState = {
loginReducer: loginReducer(state.loginReducer, action),
userReducer: userReducer(state.userReducer, action),
};
return newState;
};
// 指定为其他名称:
export default (state = {}, action) => {
const newState = {
a: loginReducer(state.a, action),
b: userReducer(state.b, action),
};
return newState;
};
解释:
初始化 store
时,会调用一次进行初始化,会将这个 newState
做为初始值保存。
所以之后分发指定 action
时,state.loginReducer
就是旧值。
redux 提供了 combineReducers
,专门用来结合 reducer
,和上面的作用一样。
// 替换如下
export default combineReducers({
loginReducer,
userReducer
})
同时可以指定为其他名称:
export default combineReducers({
a: loginReducer,
b: userReducer
})
2.3,index.js 使用
import { createStore } from "redux";
import reducer from "./reducer";
import { createAddUserAction, createUpdateUserAction, createDeleteUserAction } from "./action/userAction";
const store = createStore(reducer);
console.log(store.getState());
store.dispatch(createAddUserAction({ id: 3, name: "name3", age: 20 }));
console.log(store.getState());
store.dispatch(createUpdateUserAction(2, { name: "name22" }));
console.log(store.getState());
store.dispatch(createDeleteUserAction(1));
console.log(store.getState());
以上。