React Redux是Redux的官方React UI绑定层。它允许您的React组件从Redux存储读取数据,并将操作分派到存储以更新状态。redux是一个管理状态数据state的容器。提供了可预测的状态管理。
React Redux 8.x需要React 16.8.3或更高版本/Rect Native 0.59或更高,才能使用React Hooks。
安装
npm install react-redux
# Or
yarn add react-redux
Store
就是把它们联系到一起的对象。Store 有以下职责:
维持应用的 state;
提供 getState() 方法获取 state;
提供 dispatch(action) 方法更新 state;
通过 subscribe(listener) 注册监听器;
通过 subscribe(listener) 返回的函数注销监听器。
三大原则
1、单一数据源
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
2、State 是只读的
唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
3、使用纯函数来执行修改
为了描述 action 如何改变 state tree ,你需要编写 reducers。
action
所有数据的变化,必须通过派发(dispatch )action来更新
action是一个普通的JavaScript对象,用来描述这次更新的type和content;
使用action的好处是能够知道数据发生了什么变化,数据变化都是可以追踪,可预测的
reducer
联系state和action的一个纯函数,不能产生副作用,将传入的state和action结合起来生成一个新的state。
redux 基本使用
安装redux,使用命令:yarn dd redux
const initialState = {
counter :0
}
// reducer
function reducer(state = initialState,action){
switch(action.type){
case:"INCREMENT":
return {...state,counter:state.counter+1};
case:"DECREMENT":
return {...state,counter:state.counter-1};
case:"ADD_NUMBER":
return {...state,counter:state.counter+action.num};
case:"SUB_NUMBER":
return {...state,counter:state.counter-action.num};
default:
return state;
}
}
// store 创建时要求传入reducer
const store = redux.createStore(reducer);
// actions
const action1 = {type:"INCREMENT"};
const action2 = {type:"DECREMENT"};
const action3 = {type:"ADD_NUMBER",num:3};
const action4 = {type:"SUB_NUMBER",num:3};
//派发action ,派发之后执行reducer
store.dispatch(action1);
store.dispatch(action2);
store.dispatch(action3);
store.dispatch(action4);
优化,真实开发中我们不可能把所以代码放一起,不方便维护,这里只是基本的使用。
Provider
API概述React Redux包括一个<Provider/>组件,该组件使Redux store可用于应用程序的其余部分:
import React from 'react'
import ReactDOM from 'react-dom/client'
import { Provider } from 'react-redux'
import store from './store'
import App from './App'
// As of React 18
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<Provider store={store}>
<App />
</Provider>,
)
Hooks
React Redux提供了一对自定义React挂钩,允许您的React组件与Redux store 交互。
useSelector从存储状态中读取一个值并订阅更新,
而useDispatch返回存储的调度方法以允许您调度操作。
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import {
decrement,
increment,
incrementByAmount,
incrementAsync,
selectCount,
} from './counterSlice'
import styles from './Counter.module.css'
export function Counter() {
const count = useSelector(selectCount)
const dispatch = useDispatch()
return (
<div>
<div className={styles.row}>
<button
className={styles.button}
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
+
</button>
<span className={styles.value}>{count}</span>
<button
className={styles.button}
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
-
</button>
</div>
{/* omit additional rendering output here */}
</div>
)
}
案例
利用 react-redux 构建全局状态管理
● 创建 reducer,在的数里面判断action的type属性,然后返回状态
● 利用 createStore 来捣建 store
● 在 App,js 中导入 store
● 在 App.js 中导入 Provider,在根组件上对整个结构进行包裹,然后设置 store 属性,来统一对 store进行管理
App.js
import LayOut from './pages/LayOut.jsx';
import store from "./store";
import { Provider } from 'react-redux';
function App() {
return (
<Provider store={store}>
<div className="App">
<LayOut />
</div>
</Provider>
);
}
export default App;
LayOut 组件 ,pages/LayOut.jsx
import React from "react";
import { useCallback, useEffect } from "react";
import { setUserInfoAction } from "../store/user/action";
import { useDispatch } from "react-redux";
// import getStateUser from "../store/getter/user"
import { useStateUserInfo } from "../store/getter/user";
const LayOut = ()=>{
const dispatch = useDispatch()
const setUserInfo = useCallback((info) => dispatch(setUserInfoAction(info)), [dispatch])
const userInfo = useStateUserInfo()
const onFinish = ()=>{
setUserInfo({
name:"张三",
age:"23"
});
console.log(userInfo)
}
useEffect(() => {
console.log(userInfo)
}, [userInfo]);
return <div>
登录 保存 user info <br/>
{userInfo?.name} -- {userInfo?.age} <br/>
<button onClick={onFinish}>登录</button>
</div>
}
export default LayOut
// export default connect( mapState, mapDispatch )(MyComponent)
在src 下新建 store 文件如下
store 下面的index,js
import {combineReducers,createStore} from 'redux';
import UserReducer from "./user/reducer";
const reducer = combineReducers({
user: UserReducer,
});
const store = createStore (
reducer
);
export default store;
store 下的 user 模块 下的 action.js
import * as ActionTypes from "./actionTypes";
export const setUserInfoAction = (info) => ({
type: ActionTypes.SET_USERINFO,
info,
});
export const clearUser = () => ({
type: ActionTypes.CLEAR_USERINFO,
});
store 下的 user 模块 下的actionTypes.js
export const SET_USERINFO = "SET_USERINFO";
export const CLEAR_USERINFO = "CLEAR_USERINFO";
store 下的 user 模块 下的reducer.js
import * as actionTypes from "./actionTypes";
const initState = {
name:"",
age:""
}
export default function reducer(state = initState, action) {
const { type, info } = action
switch (type) {
case actionTypes.SET_USERINFO:
console.log(info)
return info
case actionTypes.CLEAR_USERINFO: {
return null
}
default:
return state
}
}
store 下的 getter 获取数据 user
import { useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
const getStateUser = (state) => state.user
export const useStateUserInfo = () => useSelector(getStateUser)
用例结果