redux 核心概念 action(type数据操作方式,payload参数)、reducer(初始化数据,根据action.type去执行不同操作。)、store(核心仓库数据,初始化传入reducer)
reducer 理解为催化剂,把action和store反应生成新store
redux最重要的就是从业务组建中脱离出来,作为一个数据库,对修改以及取都能做到收口的奇效
项目实践
npm i @reduxjs/toolkit react-redux
@reduxjs/toolkit
简化redux使用流程,以前需要创建actions reducers等文件夹,现在提出slice(片)概念,整合了action 和 reduce。
原来在reducer函数里判断action type
现在将reducers配置拆分成多个action操作函数
默认将action.type === slice注册名/action操作函数名
react-redux
提供 provider 组件,负责触发页面更新。
新版使用 hooks useSelector取值, useDispatch 更新
旧版 connect 函数在ui组件包一层数据逻辑层,通过prop传入redux state 和 修改方法,左手ui右手store
splice
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
// store不可直接修改,这里提供数据变异方法,是草稿副本更新完覆盖state操作。
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action) => {
state.value += action.payload
},
},
})
// 同步修改
export const { increment, decrement, incrementByAmount } = counterSlice.actions
// The function below is called a thunk and allows us to perform async logic. It
// can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This
// will call the thunk with the `dispatch` function as the first argument. Async
// code can then be executed and other actions can be dispatched
// 异步更新
export const incrementAsync = (amount) => (dispatch) => {
setTimeout(() => {
dispatch(incrementByAmount(amount))
}, 1000)
}
// The function below is called a selector and allows us to select a value from
// the state. Selectors can also be defined inline where they're used instead of
// in the slice file. For example: `useSelector((state) => state.counter.value)`
// selector 取值操作~ 组件页面行内直接取也行
export const selectCount = (state) => state.counter.value
export default counterSlice.reducer
store.js
import { configureStore } from "@reduxjs/toolkit"
import counterReducer from './userSlice.js'
const store = configureStore({
reducer: {
counter: counterReducer // slice注册名
}
})
export default store
index.js
增加Provider组件
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import store from './store/store.js'
import { Provider } from 'react-redux'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
jsx
hooks api
import {useSelector,useDispatch } from 'react-redux'
import {selectCount,increment, decrement, incrementByAmount, incrementAsync} from '../store/splice/count'
export default function StorePage() {
// 取值
const count = useSelector((state) => state.counter.value)
const count2 = useSelector(selectCount)
const dispatch = useDispatch()
return (
<div>
{count}
{count2}
// 修改值
<button onClick={()=>dispatch(increment())}>+</button>
<button onClick={()=>dispatch(decrement())}>-</button>
<button onClick={()=>dispatch(incrementByAmount(100))}>aaa</button>
<button onClick={()=>dispatch(incrementAsync(1000))}>bbb</button>
</div>
)
}
connect api
import {connect} from 'react-redux'
import {selectCount,increment} from '../store/splice/count'
function UIcomponent(props){
props.count
props.increment()
}
export default connect(
state => ({
count: state.count
}),
{
increment,selectCount
}
)(UIcomponent)