一文詳解ReactNative狀態(tài)管理redux-toolkit使用
正文
有同學(xué)反饋開(kāi)發(fā) ReactNative 應(yīng)用時(shí)狀態(tài)管理不是很明白,接下來(lái)幾篇文章我們來(lái)對(duì)比下 React 及 ReactNative 狀態(tài)管理常用的幾種框架的使用和優(yōu)缺點(diǎn)。
上一篇文章介紹了 redux 的使用,這篇文章我們來(lái)看下 redux 的升級(jí)版:redux-toolkit。
React 和 Redux-Toolkit 創(chuàng)建 Todo List App
下面是使用 React 和 Redux-Toolkit 創(chuàng)建一個(gè)簡(jiǎn)單的 Todo List App 的代碼示例
完整代碼見(jiàn)文章末尾
新建一個(gè)React應(yīng)用
- 首先,在命令行中輸入以下命令新建一個(gè)React應(yīng)用:
npx create-react-app todolist
安裝 Redux-Toolkit 和 React-Redux:
npm install @reduxjs/toolkit react-redux
創(chuàng)建一個(gè) todoSlice.ts 文件
在其中完成 action 和 reducer的創(chuàng)建「非常重要,需要保證理解」
import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { State, TODO } from "../module/todo"; const initState : State = { todos: [ { text: "zsx clean room" } ] }; //1.創(chuàng)建 Slice,每個(gè)業(yè)務(wù)一個(gè) 分片 const todoSlice = createSlice({ name: 'todo', // 這個(gè)名稱似乎沒(méi)啥用 initialState: initState, //最重要的 reducers 屬性,包括多個(gè)函數(shù) reducers: { addTodo: (state: State, action: PayloadAction<string>) => { return { todos: [...state.todos, {text: action.payload}] }; }, deleteTodo: (state: State, action: PayloadAction<string>) => { state.todos = state.todos.filter((item: TODO, index: number)=> { return item.text !== action.payload }); } } }) //2.導(dǎo)出 slice 的 action 和 reducer export const {addTodo, deleteTodo} = todoSlice.actions; export default todoSlice.reducer;
在上面的代碼里,我們使用 redux-toolkit 的 createSlice 創(chuàng)建了一個(gè)分片,分片代表某個(gè)業(yè)務(wù)的數(shù)據(jù)狀態(tài)處理,比如 todoSlice 就代表 todo 業(yè)務(wù)的所有狀態(tài)處理。
createSlice 的參數(shù),分別包括 name(名稱,似乎沒(méi)啥用)、initialState(項(xiàng)目初始狀態(tài))和 reducers,
其中 reducers 是最重要的,它就是一個(gè)對(duì)象:
reducers: { addTodo: (...) => { //... }, deleteTodo: (...) => { //... } }
對(duì)象的成員就是支持的 action 函數(shù),比如添加 todo:
addTodo: (state: State, action: PayloadAction<string>) => { //可以直接修改數(shù)據(jù) // state.todos.push({ // text: action.payload // }) //也可以返回新的 return { todos: [...state.todos, {text: action.payload}] }; }
可以看到,上面的 addTodo 類似 redux 中的 reducer,不同的在于,createSlice 中不再需要根據(jù) action type 進(jìn)行 switch case 匹配,而是直接提供了函數(shù),以執(zhí)行狀態(tài)。
需要注意的是,toolkit 中的 reducer 函數(shù),可以修改原始狀態(tài)(redux 本身是需要返回新?tīng)顟B(tài)的),這是因?yàn)樗鼉?nèi)部的特殊實(shí)現(xiàn)。
通過(guò) createSlice 創(chuàng)建完 todoSlice 后,下一步就是導(dǎo)出其中的 action 和 reducer
export const {addTodo, deleteTodo} = todoSlice.actions; export default todoSlice.reducer;
這里再次證明,slice 是 action 和 reducer 的封裝,redux-toolkit 通過(guò) slice 把 action 和 reducer 封裝到了一起,不再需要單獨(dú)創(chuàng)建 action 和 action creator。
通過(guò) redux-toolkit,我們創(chuàng)建完 slice,就可以通過(guò) slice 的 action 和 reducer 進(jìn)行使用。
創(chuàng)建 store
import { configureStore } from "@reduxjs/toolkit"; import todoReducer from "./todoSlice"; //3.配置 store,創(chuàng)建全局唯一的 stroe const store = configureStore({ //多個(gè) reducer,訪問(wèn)數(shù)據(jù)時(shí)也需要通過(guò)多層獲取 //這里的名稱,決定了獲取數(shù)據(jù)時(shí),需要訪問(wèn)的對(duì)象名稱 reducer: { todo: todoReducer } }); export default store;
和 redux 不同,redux-toolkit 使用 configureStore 創(chuàng)建 store,它的好處是當(dāng)有多個(gè) reducer 時(shí)更簡(jiǎn)單。
只需要在參數(shù)里提供一個(gè) reducer 對(duì)象即可,有多少個(gè)業(yè)務(wù),就給這個(gè)對(duì)象增加幾個(gè)成員。
{ //多個(gè) reducer,訪問(wèn)數(shù)據(jù)時(shí)也需要通過(guò)多層獲取 //這里的名稱,決定了獲取數(shù)據(jù)時(shí),需要訪問(wèn)的對(duì)象名稱 reducer: { todo: todoReducer, other: otherReducer } }
最終業(yè)務(wù)在訪問(wèn)自己的數(shù)據(jù)時(shí),通過(guò) 對(duì)象名稱可以獲取到數(shù)據(jù)。
上層組件通過(guò) Provider 分發(fā)給組件樹(shù)
const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); //分發(fā)給子元素 root.render( <Provider store={store}> <ToolkitTodoApp/> </Provider> );
這一點(diǎn)和 redux 一樣,都是使用 react-redux 的 Provider 提供給子組件,參數(shù)就是上一步創(chuàng)建的 store。
ToolkitTodoApp 是下一步要?jiǎng)?chuàng)建的 UI 組件
通過(guò)useSelector 和 useDispatch 獲取數(shù)據(jù)和分發(fā)行為
最后一步,業(yè)務(wù)組件中通過(guò) useSelector 和 useDispatch 獲取數(shù)據(jù)和分發(fā)行為:
import {useState} from "react"; import { useDispatch, useSelector } from "react-redux"; import { State, TODO } from "../module/todo"; import store from "./store"; import { addTodo, deleteTodo } from "./todoSlice"; type RootState = ReturnType<typeof store.getState>; //業(yè)務(wù)通過(guò) useSelector 獲取數(shù)據(jù);通過(guò) useDispatch 分發(fā) //比如使用 connect,更簡(jiǎn)單易懂 const ToolkitTodoApp = () => { //獲取到的是全局的 State,需要通過(guò) reducer 的名稱獲取到當(dāng)前需要的狀態(tài) const todos = useSelector((state: RootState) => { return state.todo.todos; }); const dispatch = useDispatch(); const [text, setText] = useState(''); const handleInput = (e: any) => { setText(e.target.value) } const handleAddTodo = () => { //todoSlice 導(dǎo)出的 action, 參數(shù)就是 action.payload 的類型 dispatch(addTodo(text)) setText('') } const handleDeleteTodo = (text: string) => { dispatch(deleteTodo(text)) } return ( <div style={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}> <h1>This Is Redux-Toolkit TODO App.</h1> <ul> {todos && todos.map((todo: TODO, index: any) => { return ( <li key={index}> <span>{todo.text}</span> <button style={{marginLeft: '12px'}} onClick={() => handleDeleteTodo(todo.text)}>finish</button> </li> ) })} </ul> <div style={{display: 'flex', flexDirection: 'row'}}> <input value={text} onChange={handleInput}/> <button onClick={handleAddTodo}>Add Todo</button> </div> </div> ) } export default ToolkitTodoApp;
從上面的代碼中可以看到,使用 redux-toolkit,組件里獲取狀態(tài)也更簡(jiǎn)單了,不再需要寫(xiě) connect、mapStateToProps 和 mapDispatchToProps,只需要通過(guò) react-redux 提供的 useSelector hook 即可:
const todos = useSelector((state: RootState) => { return state.todo.todos; });
需要注意的是:useSelector 里篩選自己需要的數(shù)據(jù)時(shí),需要通過(guò) reducer 的名稱獲取到當(dāng)前需要的狀態(tài),否則會(huì)出現(xiàn)字段取不到或者取錯(cuò)的情況。
比如上面的例子里,配置 store 時(shí),todo 的 reducer 的名稱叫 “todo”,那在 todo 業(yè)務(wù)里,通過(guò)useSelector 里獲取它 state 時(shí),就需要通過(guò)這個(gè)名稱 “todo” 去拿字段:
const store = configureStore({ //多個(gè) reducer,訪問(wèn)數(shù)據(jù)時(shí)也需要通過(guò)多層獲取 //這里的名稱,決定了獲取數(shù)據(jù)時(shí),需要訪問(wèn)的對(duì)象名稱 reducer: { todo: todoReducer } });
state.todo.todos;
我一開(kāi)始使用 redux-toolkit 的時(shí)候,就在這一步遇到了問(wèn)題。
另外,使用 useDispatch 分發(fā)行為時(shí)也需要注意:傳遞的參數(shù)是 createSlice 后導(dǎo)出的 action,參數(shù)類型需要和 這個(gè) action 的 payload 類型一樣。
比如前面的 todoSlice 的 reducers 里,addTodo 的 action 類型是 PayloadAction:
addTodo: (state: State, action: PayloadAction<string>) => {...}
那在調(diào)用這個(gè) action 時(shí),就需要傳遞 string 類型的參數(shù):
const handleAddTodo = () => { //todoSlice 導(dǎo)出的 action, 參數(shù)就是 action.payload 的類型 dispatch(addTodo(text)) setText('') }
- 通過(guò) createSlice 創(chuàng)建 slice,在其中指定初始狀態(tài)和支持的 action reducer
- 導(dǎo)出 slice 的 actions 和 reducer
- 通過(guò) configureStore 創(chuàng)建 store,參數(shù)是一個(gè)對(duì)象,包括上一步導(dǎo)出的 reducer
- 需要指定好業(yè)務(wù)名稱,后續(xù)取數(shù)據(jù)要用
- 通過(guò) Provider 分發(fā)給組件樹(shù)
- 業(yè)務(wù)組件中通過(guò) useSelector 和 useDispatch 獲取數(shù)據(jù)和分發(fā)行為
可以看到,redux-toolkit 與 redux 相比,不需要?jiǎng)?chuàng)建 action creator 和 connect,簡(jiǎn)化了開(kāi)發(fā)步驟。
以上就是一文詳解ReactNative狀態(tài)管理redux-toolkit使用的詳細(xì)內(nèi)容,更多關(guān)于ReactNative狀態(tài)管理redux-toolkit的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React?hooks?useState異步問(wèn)題及解決
這篇文章主要介紹了React?hooks?useState異步問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08React路由跳轉(zhuǎn)的實(shí)現(xiàn)示例
在React中,可以使用多種方法進(jìn)行路由跳轉(zhuǎn),本文主要介紹了React路由跳轉(zhuǎn)的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12React基礎(chǔ)-JSX的本質(zhì)-虛擬DOM的創(chuàng)建過(guò)程實(shí)例分析
這篇文章主要介紹了React基礎(chǔ)-JSX的本質(zhì)-虛擬DOM的創(chuàng)建過(guò)程,結(jié)合具體實(shí)例形式分析了虛擬dom的基本原理與實(shí)現(xiàn)方法,需要的朋友可以參考下2023-05-05React項(xiàng)目中報(bào)錯(cuò):Parsing error: The keyword &a
ESLint 默認(rèn)使用的是 ES5 語(yǔ)法,如果你想使用 ES6 或者更新的語(yǔ)法,你需要在 ESLint 的配置文件如:.eslintrc.js等中設(shè)置 parserOptions,這篇文章主要介紹了React項(xiàng)目中報(bào)錯(cuò):Parsing error: The keyword 'import' is reservedeslint的問(wèn)題及解決方法,需要的朋友可以參考下2023-12-12React合成事件原理及實(shí)現(xiàn)(React18和React16)
本文主要介紹了React合成事件原理及實(shí)現(xiàn),包含React18和React16兩種版本,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02react中antd Upload手動(dòng)上傳的示例
本文主要介紹了react中antd Upload手動(dòng)上傳的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04