一、Redux
集中狀態管理工具,不需要react即可使用,每個store的數據都是獨立于組件之外的
vue小鏈接:vuex/pinia
基本使用
Redux將數據修改流程分成三個概念,state、action和reducer
state -?一個對象 存放我們管理的數據狀態
action - 一個對象 描述你如何修改數據
reducer - 一個函數 根據action的描述生成新的state
<button id="decrement">-</button>
<span id="count">0</span>
<button id="increment">+</button><script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script><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. 使用reducer函數生成store實例const store = Redux.createStore(reducer)// 3. 通過store實例的subscribe訂閱數據變化// 回調函數可以在每次state發生變化的時候自動執行store.subscribe(() => {console.log('state變化了', store.getState())document.getElementById('count').innerText = store.getState().count})// 4. 通過store實例的dispatch函數提交action更改狀態 const inBtn = document.getElementById('increment')inBtn.addEventListener('click', () => {// 增store.dispatch({type: 'INCREMENT'})})const dBtn = document.getElementById('decrement')dBtn.addEventListener('click', () => {// 減store.dispatch({type: 'DECREMENT'})})// 5. 通過store實例的getState方法獲取最新狀態更新到視圖中</script>
react中使用redux
相關工具
Redux Toolkit 簡化redux書寫邏輯
react-redux 鏈接Redux和React的中間件
npm i @reduxjs/toolkit react-redux
?安裝成功
目錄創建
創建src/store,modules存放子模塊
counterStore.js
//1 導入并創建store
import {createSlice} from "@reduxjs/toolkit"const counterStore = createSlice({name:'counter',// 初始狀態initialState:{count:0},// 更新狀態的方法reducers:{inscrement(state){state.count++},descrement(state){state.count --}}
})const {inscrement, descrement} = counterStore.actions
const reducer = counterStore.reducerexport{inscrement,descrement
}export default reducer
store/index.js
集成store/modules中所有子模塊
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./modules/counterStore"// 將子模塊中的所有store合成一個根store方便訪問
const store = configureStore({reducer:{counter:counterReducer,}
})export default store
src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import store from "./store"
import { Provider } from 'react-redux';const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(// 通過react-redux提供的Provider 給組件注入store 使得redux定義的store能夠被react組件使用<Provider store={store}><App /></Provider>
);
App.js
useDispatch() 通過這個來派發reducer修改狀態
import { useSelector, useDispatch } from "react-redux";
import {inscrement, descrement} from "./store/modules/counterStore"
function App() {const { count } = useSelector(state => state.counter)const dispatch = useDispatch()return (<div className="App"><button onClick={() => dispatch(inscrement())}>+</button>{count}<button onClick={() => dispatch(descrement())}>-</button></div>);
}export default App;
然后就完成了:
進階版-提交action時傳參
counterStore.js
增加了一個addToNum函數
//1 導入并創建store
import {createSlice} from "@reduxjs/toolkit"const counterStore = createSlice({name:'counter',// 初始狀態initialState:{count:0},// 更新狀態的方法reducers:{inscrement(state){state.count++},descrement(state){state.count --},addToNum(state, action){// dispatch調用該方法時傳入的參數就存放在action.payloadstate.count += action.payload}}
})const {inscrement, descrement, addToNum} = counterStore.actions
const reducer = counterStore.reducerexport{inscrement,descrement,addToNum
}export default reducer
?App.js
增加了兩個值,傳入不同參數
import { useSelector, useDispatch } from "react-redux";
import {inscrement, descrement, addToNum} from "./store/modules/counterStore"
function App() {const { count } = useSelector(state => state.counter)const dispatch = useDispatch()return (<div className="App"><button onClick={() => dispatch(inscrement())}>+</button>{count}<button onClick={() => dispatch(descrement())}>-</button><button onClick={() => dispatch(addToNum(10))}>+ 10</button><button onClick={() => dispatch(addToNum(-10))}>- 10</button></div>);
}export default App;
再進階版-異步狀態操作
channelStore.js
import {createSlice} from '@reduxjs/toolkit'
import axios from 'axios'const channelStore = createSlice({name:'channel',initialState:{channelList:[]},reducers:{getChannels(state, action){state.channelList = action.payload}}
})const {getChannels} = channelStore.actions//單獨寫一個異步action的函數 異步操作處理完畢后再調用同步action修改狀態
const getChannelList = () => {return async(dispatch) => {const res = await axios.get('http://geek.itheima.net/v1_0/channels')dispatch(getChannels(res.data.data.channels))}
}export {getChannelList}const reducer = channelStore.reducer
export default reducer
?App.js
import { useSelector, useDispatch } from "react-redux";
import {inscrement, descrement, addToNum} from "./store/modules/counterStore"
import {getChannelList} from "./store/modules/channelStore"
import {useEffect} from 'react'
function App() {const { count } = useSelector(state => state.counter)const { channelList } = useSelector(state => state.channel)const dispatch = useDispatch()useEffect(()=> {dispatch(getChannelList())}, [dispatch])return (<div className="App"><button onClick={() => dispatch(inscrement())}>+</button>{count}<button onClick={() => dispatch(descrement())}>-</button><button onClick={() => dispatch(addToNum(10))}>+ 10</button><button onClick={() => dispatch(addToNum(-10))}>- 10</button><ul>{channelList.map(item => <li key={item.id}>{item.name}</li>)}</ul></div>);
}export default App;
調試工具redux devtools
直接在chorme商店里下載
?