ReactNative?狀態(tài)管理redux使用詳解
正文
有同學反饋開發(fā) ReactNative 應用時狀態(tài)管理不是很明白,接下來幾篇文章我們來對比下 React 及 ReactNative 狀態(tài)管理常用的幾種框架的使用和優(yōu)缺點。
首先來看下 redux 怎么使用。
以下是使用 React 和 Redux 創(chuàng)建 todo list 的一般過程,完整代碼見文章末尾:
安裝和配置開發(fā)環(huán)境
安裝 Node.js 和 create-react-app 腳手架,用于快速創(chuàng)建 React 應用程序
npx create-react-app playpage_ts -template typescript
安裝 React 和 Redux 關聯庫 redux 和 react-redux
npm install @reduxjs/toolkit react-redux
定義數據結構
這里我們假設 TODO 就是一個文本
export type TODO = {
text: string
}
//1.定義狀態(tài)數據
export type State = {
todos: TODO[]
}
- 定義行為 action,比如添加、刪除:
//2.定義行為
//action
export const ADD_TODO = 'ADD_TODO';
export const DELETE_TODO = 'DELETE_TODO';
//action creator
const ACTION_CREATOR_ADD_TODO = (text:string) => {
return {type: ADD_TODO, payload: text}
};
const ACTION_CREATOR_DELETE_TODO = (text:string) => {
return {type: DELETE_TODO, payload: text}
};
//分發(fā)數據變更操作,接收 store.dispatch
export function DISPATCH_ADD_TODO(dispatch: any) {
return (text: string) => {
dispatch(ACTION_CREATOR_ADD_TODO(text))
}
}
export function DISPATCH_DELETE_TODO(dispatch: any) {
return (text: string) => {
dispatch(ACTION_CREATOR_DELETE_TODO(text))
}
}
上面的代碼里,首先定義了行為類型( action type):ADD_TODO 和 DELETE_TODO,它們用于唯一標識一個狀態(tài)改變行為。
然后創(chuàng)建了兩個 action creator :ACTION_CREATOR_ADD_TODO 和 ACTION_CREATOR_DELETE_TODO,它們用于創(chuàng)建符合 reducer 約定的 action 對象,其中 type 標識行為類型,payload 表示傳遞的數據。
最后創(chuàng)建了兩個函數:DISPATCH_ADD_TODO 和 DISPATCH_DELETE_TODO,它們用于分發(fā)數據變更操作,簡化后續(xù) connect 里的代碼。
然后創(chuàng)建行為處理函數 todoReducer
import { State, TODO } from "./model";
import { ADD_TODO, DELETE_TODO } from "./todoActions";
const initState : State = {
todos: [
{
text: "clean room"
}
]
};
//3.創(chuàng)建行為處理函數
const todoReducer = (state: State = initState, action: any): State => {
switch(action.type) {
case ADD_TODO:
//返回一個新的狀態(tài)樹
return {
todos: [...state.todos, {text: action.payload}]
};
case DELETE_TODO:
console.log('todoReducer delete >>>' + action.payload)
const todos = state.todos.filter((item: TODO, index: number)=> {
return item.text != action.payload
});
return {
todos
}
default:
console.log('return default>>>' + JSON.stringify(state))
return state;
}
};
export default todoReducer;
todoReducer 的作用是根據行為,返回新的狀態(tài)。
參數是先前的狀態(tài) state 和要執(zhí)行的行為 action,根據 action type 行為類型,返回不同的數據。
需要注意的是,reducer 中不能修改老數據,只能新建一個數據。
- 創(chuàng)建一個 store,參數就是上面創(chuàng)建的行為處理函數:
import { createStore } from 'redux';
import todoReducer from './reducers';
//4.創(chuàng)建 store,提供全局的狀態(tài)和行為處理
const store = createStore(
todoReducer
);
//監(jiān)聽數據變化
store.subscribe( () => {
console.log("store changed >>>" + JSON.stringify(store.getState()))
})
export default store;
import { createStore } from 'redux';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
export default store;
- 分發(fā)給子元素:
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { Provider } from 'react-redux';
import ReduxTodoApp from './ReduxTodoApp';
import store from './redux/store';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
//5.分發(fā)給子元素
root.render(
<Provider store={store}>
<ReduxTodoApp/>
</Provider>
);
上面的代碼中,我們使用使用 react-redux 的 Provider 包圍了 App 組件,這樣整個 App 組件都可以獲取到 Store 中的狀態(tài)和行為處理函數。
ReduxTodoApp 是下一步要創(chuàng)建的 UI 組件
創(chuàng)建 UI 組件:
import {useState} from "react";
import { connect } from "react-redux";
import { State, TODO } from "./redux/model";
import {DISPATCH_ADD_TODO, DISPATCH_DELETE_TODO } from "./redux/todoActions";
//6.數據和 action 函數需要通過 prop 訪問
function ReduxTodoApp (prop: {todos: TODO[], addTodo: any, deleteTodo: any}) {
const {todos, addTodo, deleteTodo} = prop;
const [text, setText] = useState('');
const handleInput = (e: any) => {
setText(e.target.value)
}
const handleAddTodo = () => {
addTodo(text)
setText('')
}
const handleDeleteTodo = (text: string) => {
deleteTodo(text)
}
return (
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
<h1>This Is Redux TODO App.</h1>
<ul>
{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>
)
}
//外部的數據(即state對象)如何轉換為 UI 組件的參數
//mapStateToProps會訂閱 Store,每當state更新的時候,就會自動執(zhí)行,重新計算 UI 組件的參數,從而觸發(fā) UI 組件的重新渲染。
const mapStateToProps = (state: State) => {
console.log('mapStateToProps >>> ' + JSON.stringify(state))
//返回的是一個對象,需要根據屬性名訪問
return {
todos: state.todos
}
}
//建立 UI 組件的參數到store.dispatch方法的映射
//定義了哪些用戶的操作應該當作 Action,傳給 Store
const mapDispatchToProps = (dispatch: any, ownProps: any) => {
//返回一個 Prop 對象
return {
addTodo: DISPATCH_ADD_TODO(dispatch),
deleteTodo: DISPATCH_DELETE_TODO(dispatch)
}
};
//5.組件接收數據和分發(fā)行為
export default connect(mapStateToProps, mapDispatchToProps) (ReduxTodoApp);
上面的代碼中,使用 connect 包裝了 UI 組件。
connect 的第一個參數 mapStateToProps 用于返回當前 UI 組件需要的數據,這里我們獲取到 Store 中的 todos 列表。
第二個參數 mapDispatchToProps 用于返回當前 UI 組件需要向外分發(fā)的狀態(tài)操作行為,這里我們需要分發(fā)兩個行為:添加 todo 和刪除 todo,通過調用第二步中創(chuàng)建的 DISPATCH_ADD_TODO 和 DISPATCH_DELETE_TODO 實現。
正如名稱所示,mapStateToProps 和 mapDispatchToProps,最終都會向 Props 里添加成員。
這樣,我們的 UI 組件的 props 就會包含 mapStateToProps 中返回的狀態(tài)與 mapDispatchToProps 中的函數,也就是這樣:
{
todos: TODO[],
addTodo: any,
deleteTodo: any
}
注意名稱需要一致。
然后我們就可以在 UI 組件中通過 prop.todos 獲取數據,通過 prop.addTodo 或者 prop.deleteTodo 通知修改數據。
總結一下,通過最原始的 redux 管理狀態(tài)分這幾步:
定義數據結構類型,也就是前面的 State
- 定義要進行的數據修改行為 (action type),也就是前面的 ADD_TODO 和 DELETE_TODO
- 然后創(chuàng)建 action creator,創(chuàng)建 reducer 里需要的 action 對象
- 然后創(chuàng)建調用 store.dispatch 的函數,簡化 mapDispatchToProps 的代碼
有了行為后,然后就是處理行為,也就是 reducer
在其中根據 action type,返回不同的狀態(tài)
有了 reducer 后,store 就齊全了,可以通過 createStore 創(chuàng)建一個全局唯一的 store
通過 react-redux 的 Provider 包裹整個 app 組件,把 store 分發(fā)給所有組件
- 最重要的一步:在 UI 組件里獲取數據和分發(fā)行為
- 使用 react-redux 的 connect 包裹 UI 組件
- connect 的第一個參數返回一個對象,在其中獲取 UI 組件里需要的數據
- 第二個參數返回一個對象,其中包括要向外分發(fā)的行為
- 在 UI 組件里通過 props.xxx 的方式獲取數據和分發(fā)行為
步驟有些繁瑣,但重要的是,行為和行為處理都拆分開,及時業(yè)務變得復雜,后續(xù)拓展也比較輕松。
如果要分析某個狀態(tài)修改操作,在 reducer 里增加日志即可定位到,這就是 redux 宣稱的優(yōu)勢:“可追溯”。
以上就是ReactNative 狀態(tài)管理redux使用詳解的詳細內容,更多關于ReactNative狀態(tài)管理redux 的資料請關注腳本之家其它相關文章!
相關文章
vite?+?react?+typescript?環(huán)境搭建小白入門教程
這篇文章主要介紹了vite?+?react?+typescript?環(huán)境搭建小白入門教程,本文通過示例圖文相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-12-12
react-router-dom6(對比?router5)快速入門指南
這篇文章主要介紹了快速上手react-router-dom6(對比?router5),通過本文學習最新的react-router-dom?v6版本的路由知識,并且會與v5老版本進行一些對比,需要的朋友可以參考下2022-08-08
使用useMutation和React Query發(fā)布數據demo
這篇文章主要為大家介紹了使用useMutation和React Query發(fā)布數據demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12

