react-redux实操与浅谈
什么是react-redux?
React-Redux是Redux的官方React绑定库。它能够使你的React组件从Redux store中读取数据,并且向store分发actions以更新数据。
你可以把react-redux看成单独的一个库,里面有封装好的API帮助您更好的使用redux。因为用原生redux和react结合使用的时候,每次都要载入store,而且派发完action修改数据后还要调用subscribe去监听,在监听里更新事件,React-Redux规避了这些麻烦。
在react-redux应用中使用Hooks
1. 创建store
开始需要把整个应用包裹在<Provider>
组件中,确保store可以被整个组件树访问到:
可以把store
看成一个专门存储数据的一个仓库,也可以把它看成是一个很大的JavaScript对象。创建store时需要一个reducer作为参数关联到store上。
import { createStore } from 'redux';
import rootReducer from './reducers';
const store = createStore(reducer)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
document.getElementById('root')
);
此步操作之后,可以引用所有的react-redux hooks并可以在函数组件中使用它们。
2. 创建actions
什么是action?
根据官方的释义,action是把数据从应用传到store的有效载荷。它是store数据的唯一来源。
下图是官方给出的redux工作流。如果把这个过程看成去图书馆借书,component就是借阅者,store就是图书的贮藏室,那么action就相当于借书卡。action实际上是一种操作,有了借书卡我们可以执行借书还书这个操作,并且知道借换什么书。那么同理,action负责向store执行数据流的一个操作,并且知道是哪条数据。一般来说会通过dispatch()将action传到store。
Action 本质上是 JavaScript 普通对象。我们约定,action 内必须使用一个字符串类型的 type
字段来表示将要执行的动作。多数情况下,type
会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。
创建action。
根据上图可以看到有两个文件,actionTypes主要用于引入action的类型。类似这样:
而index文件里面主要是函数,它作为dispatch参数。其中type这个字段是必须要有的,它决定了将要要执行的动作。多数情况下,type会被定义成字符串常量。除了type字段外,action对象的结构完全由你自己决定。
3. 创建reducer
1. 什么是reducer?
reducer指定了应用状态的变化如何相应actions并发送到store的。记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。当然上述是官方的描述,通俗一点的来说reducer就是一个纯函数,接受之前的state和action作为参数,返回一个更新的state。一个组件可以有多个action,但是只能有一个reducer,一个reducer对应一个初始状态。可以在reducer根目录文件里绑定多个reducer,使之成为一个root reducer,在store里可以用一个root reducer去构建整个store的state树。
2. 创建reducer
一个组件可以有多个action,但是只能有一个reducer,一个reducer对应一个初始状态。可以在reducer根目录文件里绑定多个reducer,使之成为一个root reducer,在store里可以用一个root reducer去构建整个store的state树。
import { STAFF_LIST } from "@/actions/actionType";
const staffListReducer = (state = {}, action) => {
let newState = {};
switch (action.type) {
case STAFF_LIST:
newState = {...state, staffList: action.list}
return newState;
default:
return state;
}
}
export default staffListReducer;
下述代码就是将多个reducer合并成一个reducer:
import { combineReducers } from 'redux';
import msgReducer from './msgReducer';
import baseInfoReducer from './baseInfoReducer';
import notificationReducer from './notificationReducer';
import chatReducer from './chatReducer';
import staffListReducer from './staffListReducer';
import lineUpListReducer from './lineUpStaffList';
export default combineReducers({
chatMsg: msgReducer,
baseInfo: baseInfoReducer,
notificationInfo: notificationReducer,
chatInfo: chatReducer,
staffList: staffListReducer,
lineUpStaffList: lineUpListReducer,
})
4. 使用useDispatch和useSelector分发和提取数据:
1. useDispatch()
这个hook返回redux store的dispatch函数的引用。可以用来使用dispatch(分发)某些需要action。
我这边直接节选了项目里面的一部分代码。_doctorGetChatStaffList
主要用于请求接口数据的,将请求道德数据分别分发到两个不同的action上。
import { useDispatch } from 'react-redux';
import { staff_list, line_up_staff_list } from '@/actions';
const dispatch = useDispatch();
async function _doctorGetChatStaffList() {
const res = await doctorGetChatStaffList();
let lineUpStaffList = _.get(res, ['result', 'lineUpStaffList'], []);
let staffList = _.get(res, ['result', 'staffList'], []);
dispatch(line_up_staff_list(lineUpStaffList));
dispatch(staff_list(staffList));
}
2. useSelector()
通过传入selector函数,就可以从redux的store中获取state数据。
import { useSelector} from 'react-redux';
const lineUpStaffList = useSelector(state => state.lineUpStaffList.lineUpStaffList);
const staffList = useSelector(state => state.staffList.staffList);
总体而言,useSelector提取数据的机制还是比较简单的。
总结
我可以把该项目整个的store里面的数据打印下来。
可以看到上图里面的数据全是由的reducer这个函数来定义的对象的。
我们再看reducer内部:reducer根据派发的type类型来进行不同的数据处理。
我们再看actionType内部:这边定义action的type类型,用于区别不同的数据流操作。
onType内部:这边定义action的type类型,用于区别不同的数据流操作。