Redux 是一個用於 JavaScript 應用程式的狀態管理庫。它可以幫助您管理應用程式中的狀態,並確保狀態的一致性和可預測性。
Redux 主要用於處理大型應用程式中的複雜狀態邏輯,例如跨元件共享狀態、處理非同步資料流等。
Redux 的核心概念包括:
-
Store(儲存):Redux 應用程式的狀態(state)被統一儲存在一個稱為 Store 的物件中。這個狀態是隻讀的,唯一改變狀態的方式是透過分發(dispatching)一個 action。
-
Action(動作):Action 是描述發生了什麼事情的純 JavaScript 物件。它必須包含一個
type
屬性來指明動作的型別,通常還會包含一些與動作相關的資料。 -
Reducer(歸納器):Reducer 是一個純函式,接收先前的狀態和一個 action,並返回新的狀態。Reducer 負責根據 action 更新應用程式的狀態。
-
Dispatch(分發):使用
store.dispatch(action)
方法來分發一個 action,這是唯一能改變狀態的方法。 -
Selector(選擇器):選擇器用於從 Store 中提取部分狀態資料,以便在應用程式的元件中使用。
Redux 的工作流程是:當應用程式中的某個地方發生了變化,比如使用者互動或者網路請求返回資料,就會建立一個對應的 action 並被分發到 store 中。然後,相應的 reducer 會根據 action 更新 store 中的狀態。最後,React 元件可以訂閱 store 中的狀態,並根據狀態的變化來更新介面。
透過這種方式,Redux 提供了一種可預測且一致的狀態管理機制,使得應用程式的狀態變化變得容易追蹤和除錯。這使得 Redux 成為處理大型複雜應用程式狀態的理想選擇。
一、CDN引入JS使用Redux
1.定義一個reducer函式(根據當前想要做的修改返回一個新的狀態)
2.使用createStore方法傳入reducer函式 生成一個store例項物件
3.使用store例項的subscribe訂閱資料的變化(資料一旦變化,可以得到通知)
4.使用store例項的dispatch方法提交action物件觸發資料變化(告訴reducer你想怎麼改資料)(修改資料的唯一方式)
5.使用store例項的getState方法獲取最新的狀態資料更新到檢視中
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.1.1/redux.min.js"></script> <div class="sum"> <button id="reduce"> - </button> <span id="num"> 0 </span> <button id="add"> + </button> </div> <script> //1.定義reducer函式 : 根據不用的action函式,返回不同的state //state:管理資料的初始狀態 //action:物件 type 標記當前想做什麼樣的修改 function reducer(state={count:0},action){ //資料不可變,基於原始狀態生成新的狀態 if(action.type === 'INCREMENT'){ return {count:state.count+1} } if(action.type === 'DECREMENT'){ return {count:state.count-1} } return state } //2.使用createStore方法傳入reducer函式 生成一個store例項物件 const store = Redux.createStore(reducer) //3.透過store例項的subscribe訂閱資料變化 store.subscribe(()=>{ console.log('state變化了',store.getState()) document.getElementById('num').innerText=store.getState().count }) //4.使用store例項的dispatch方法提交action物件觸發資料變化 const inBtn = document.getElementById('add') const dBtn = document.getElementById('reduce') inBtn.addEventListener('click',()=>{ store.dispatch({ type:'INCREMENT' }) }) dBtn.addEventListener('click',()=>{ store.dispatch({ type:'DECREMENT' }) }) </script>
二、creatReactApp(框架)使用Redux
1.建立環境
npm i @reduxjs/toolkit react-redux
(1) Redux Toolkit(RTK) 官方推薦編寫Redux邏輯的方式,是一套工具的集合集,簡化書寫方式
(2)react-redux 用來連結Redux和React元件的中介軟體
(3)目錄結構設計
2.使用方式
(1)配置子模組(子store)
import {createSlice} from "@reduxjs/toolkit" //createSlice 建立store的方法 const countStore = createSlice({ name : 'counter', //給模組一個名字 initialState:{ count : 0 }, //初始化state reducers :{ add(state){ state.count++ }, reduce(state){ state.count-- }, }//修改狀態的方法 同步方法 支援直接修改 }) //解構出來actionCreater函式==》解構出來的方法叫做actionCreater (也就是說這些方法是生成action物件的) const {add,reduce} = countStore.actions //獲取reducer函式 const reducer = countStore.reducer //匯出建立action物件的函式和reducer函式 export {add,reduce,addNum} export default reducer
(2)index.js入口檔案配置根store並組合子store
import {configureStore} from "@reduxjs/toolkit" //組合子模組的方法 import countReducer from './modules/counterStore' //匯入子模組 //配置 const store=configureStore({ reducer:{ counter : countReducer, } }) //匯出 export default store
(3)在react中注入store
import store from './store/index' import {Provider} from 'react-redux' //react-redux負責把Redux和React連線起來,內建Provider元件透過store引數把建立好的store例項注入到應用中,連結正式建立 //把App根元件渲染到id為root的dom節點 const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <Provider store={store}> <App /> </Provider> );
(4)使用store中的資料 修改store中的資料
import { useSelector,useDispatch } from 'react-redux'; //在React元件中使用store的資料,需要用到一個鉤子函式useSelector,他的作用是把store中的資料對映到元件中 import {add,reduce} from './store/modules/counterStore' //匯入actionCreater
function App(){ const {count} = useSelector(state=>state.counter) const dispatch = useDispatch() //React元件中修改store中的資料需要藉助另一個hook函式 useDispatch ,他的作用是生成提交action物件的dispatch函式 return <div> <div> <button onClick={()=>{ dispatch(reduce()) }}>-</button> <span>{count}</span> <button onClick={()=>{ dispatch(add()) }}>+</button> </div> </div> }
(5)總結
元件中使用useSelector (hook函式)獲取store中的物件
元件中使用useDispatch(hook函式)獲取dispatch方法
執行store模組中匯出的actionCreater方法就能得到要提交的action物件
3.action傳參
(1)在reducer的同步修改方法中新增action物件引數
const countStore = createSlice({ name : 'counter', //給模組一個名字 initialState:{ count : 0 }, //初始化state reducers :{ add(state){ state.count++ }, reduce(state){ state.count-- }, addNum(state,action){ state.count= state.count+action.payload
} //在reducer的同步修改方法中新增action物件引數 }//修改狀態的方法 同步方法 支援直接修改 }) //解構出來actionCreater函式==》解構出來的方法叫做actionCreater (也就是說這些方法是生成action物件的) const {add,reduce,addNum} = countStore.actions //獲取reducer函式 const reducer = countStore.reducer export {add,reduce,addNum} export default reducer
(2)呼叫actionCreater的時候傳遞引數,引數會被傳遞到action物件的payload屬性上
<div> <button onClick={()=>{ dispatch(reduce()) }}>-</button> <span>{count}</span> <button onClick={()=>{ dispatch(add()) }}>+</button> <button onClick={()=>{ dispatch(addNum(10)) }}> +10 </button> <button onClick={()=>{ dispatch(addNum(20)) }}> +20 </button> </div> //呼叫actionCreater的時候傳遞引數
4.非同步操作
(1)配置store
(2)同步修改
const channelStore=createSlice({ name : 'channel', //定義子store的名字 initialState :{ channelList : [] //初始化資料的狀態 }, reducers:{
//定義修改資料的同步方法 setList(state,action){ state.channelList = action.payload } } })
(3)非同步修改
//非同步請求
const channelAsync=()=>{ return async (dispatch)=>{ const res = await axios.get('。。。') //封裝非同步請求獲取資料 dispatch(setList(res.data.data.channels)) //呼叫同步actionCreater傳入非同步資料生成的一個action物件,並使用dispatch提交 } }
(4)使用store的資料
(5)diapatch提交action物件更新store
const {channelList} = useSelector(state=>state.channel) const dispatch = useDispatch() //React元件中修改store中的資料需要藉助另一個hook函式 useDispatch ,他的作用是生成提交action物件的dispatch函式 useEffect(()=>{ dispatch(channelAsync()//非同步操作生成的就不是一個action物件了 是一個action函式) },[dispatch])