react-redux落地方案

249 阅读4分钟
React 状态管理 的概述
redux 其实是一个第三方 数据状态管理的库,它不仅仅可以和react 结合使用,你也可以把它应用到 vue 中 
Redux API
createStore(reducer, [preloadedState], enhancer); 
  - reducer (Function): 接收两个参数,分别是当前的 state 树和要处理的 action,返回新的 state 树。
  - [preloadedState] (any): 初始时的 state。 在同构应用中,你可以决定是否把服务端传来的 state 后传给它,或者从之前保存的用户会话中恢复一个传给它。如果你使用 combineReducers 创建 reducer,它必须是一个普通对象,与传入的 keys 保持同样的结构。否则,你可以自由传入任何 reducer 可理解的内容。
  - enhancer (Function): Store enhancer 是一个组合 store creator 的高阶函数,返回一个新的强化过的 store creator。这与 middleware 相似,它也允许你通过复合函数改变 store 接口。
  - 返回值 (Store): 保存了应用所有 state 的对象。改变 state 的惟一方法是 dispatch action。你也可以 subscribe 监听 state 的变化,然后更新 UI。
reducer 
  - reducer(state,action)
  
Store 
  - getState()
  - dispatch(action)dispatch传入action对象,触发reducer;
  - subscribe(listener)subscribe用来监控state的变化,返回的参数用来取消监控;
  - replaceReducer(nextReducer)replaceReducer替换reducer;
​
combineReducers(reducers)
  将 reducer 函数拆分成多个单独的函数,拆分后的每个函数负责独立管理 state 的一部分
​
applyMiddleware(...middlewares) 中间件
​
Redux三大原则
1. 单一数据源:整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中
​
2. state是只读的:唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象
​
3. 使用纯函数来执行修改

高阶函数和纯函数

高阶函数,至少满足下面一个条件的函数:1.接受一个或多个函数作为输入;2.输出一个函数

纯函数,1.相同的输入永远返回相同的输出;2.不改变函数的输入值;3.不依赖外部环境状态;4.无任何副作用

react-redux 的学习
类似于 Vue,React 中组件之间的状态管理 第三方包为:react-redux。react-redux 其实是 Redux的官方React绑定库,它能够使你的React组件从Redux store中读取数据,并且向store分发actions以更新数据。
react-redux: 其实是帮我们封装了 redux 连接 react 的一些操作,使用 react-redux 可以非常简单的在 react 中使用 redux 来管理我们应用的状态。
​
redux-thunk:使redux的action能够写异步方法,本身action中是不能写异步方法的,用了redux-thunk才可以。
react-redux API
react-redux 提供了两个常用的 api 
​
Provider: 组件之间共享的数据是 Provider 这个顶层组件通过 props 传递下去的,store          必须作为参数放到Provider组件中去。connect: 提供了组件获取 store 中数据或者更新数据的接口。
react-redux 落地操作(typescript 版)
1. 安装相关npm包
npm install redux react-redux redux-thunk --save
2. 创建仓库

在src目录下创建store文件夹继续在这个文件下创建index.ts 以及reducer.ts

image-20220526110003197.png

index.ts

import { createStore, applyMiddleware } from "redux";
import reducer from "./reducer";
import thunk from "redux-thunk";
​
const store = createStore(reducer, applyMiddleware(thunk));
export default store;
​

reducer.ts

import { combineReducers } from "redux";
​
const initCount = {
    count: 0,
};
​
// 修改count的方法
function count(state = initCount, action:any) {
    switch (action.type) {
        case 'COUNT_ADD':
            return {
                ...state,
                count: state.count + 1
            }
        case 'COUNT_REDUCE':
            return {
                ...state,
                count:state.count - 1
            }
        default:
            return state
    }
}
// combineReducers 合并多个reducer最终返回一个集成的reducer
export default combineReducers({
    count,
});
​
3. 全局配置store (通过Provider)
import { createRoot } from 'react-dom/client';
import './common/style/globsl.css'
import App from './App';
import { Provider } from "react-redux";
import store from './store'const container:any = document.getElementById('root');
const root = createRoot(container);
// 装载
root.render(
    <Provider store={store}>
        <App />
    </Provider>
);
​
4. 在其他页面使用store数据

可以使用 react-redux的 connect去实现但是 但是,这里比较偏向函数是组件所以采用相关hooks来实现

/**
 * hooks
 * useDispatch获取dispatch
 * useStore获取store
 * useSelector获取state
 */
import { useDispatch, useSelector, useStore } from "react-redux"
import {  Button } from 'antd';
​
const Homeone = (props:any) => {
    const dispatch = useDispatch();
    const count = useSelector((state:any)=>{
        return state.count.count
    });
    const store = useStore();
    console.log( 'store',store);
    // 可以获取所有的仓库数据
    console.log( 'store.getState',store.getState());
    const changeCOunt =(type:string)=>{
        dispatch({ type })
    }   
    return (
        <>
            <div>当前页面信息 { count } </div>
            <Button onClick={ ()=> changeCOunt('COUNT_ADD') }>添加</Button>
            <Button onClick={ ()=> changeCOunt('COUNT_REDUCE') }>减少</Button>
        </>
    )
}
export default Homeone;
6. 最终效果

test.gif