redux及react-redux

redux

这篇文章谈一谈仓库redux。

首先,学习任何东西都离不开官网。在此附上官网网址

Redux - A predictable state container for JavaScript apps. | Redux

1.什么是redux?

从如下几个方面:

redux在一个项目中可集中管理状态(数据)和逻辑代码,让你开发出强大的功能。

redux一般在中大型项目较为适用,小型项目建议使用订阅发布。

主要用于处理各个组件之间的通信问题。

2.使用redux的三大原则–规范

1.整个应用的数据state,只存放在唯一的store中。

2.state是只读的,唯一改变state数据的方法,是通过action自定义事件去修改。action是一个对象。通过Store.dispatch()去调用。

3.action自定义事件是需要通过纯函数的方式去触发的,因此需要编写与useReducer结构类似的函数去修改。reduce函数有两个参数:

参数一:上一次state的数据

参数二:传递过来的action

reduce函数要返回新的state数据。

3.原理过程分析:

在这里插入图片描述

初始化阶段:

仓库store-视图view(组件)

1.首先使用最顶层的reducer函数,创建redux-store。

​ createStore(callback)接受一个回调函数。这个回调函数就是最顶层的reducer函数

2.store调用一次reducer函数,并将返回值作为最新的state数据

3.与view框架交互,并将state数据渲染到UI视图层上面去,同时监听store的存在,以便知道state的更新

更新阶段

1.用户通过行为触发事件

2.通过store.dispatch()一个action给reducer进行state数据的处理。

3.此时数据虽然更改了,但有一个问题,没有触发视图的更新。有两种解决方案,一种是使用useState中的函数,还有一种就是重新渲染app组件。可能大家会认为非常损耗性能,但diff算法帮我们节省了性能

4.store 通知所有订阅过的 UI,通知它们 store 发生更新每个订阅过 store 数据的 UI 组件都会检查它们需要的 state 部分是否被更新。发现数据被更新的每个组件都强制使用新数据重新渲染,紧接着更新网页

4.使用

安装redux

npm i redux

然后就可以使用了


计数器小demo:

建立redux文件夹

store.js

import { createStore } from 'redux'
import { aa } from './reducers'
export default createStore(aa)

reducers.js

function aa(state = { num: 1 }, actions) {
    console.log(state, actions);
    let num = state.num
    switch (actions.type) {
        case "add":
            num = num + actions.data
            return { num }
        default:
            break;
    }
    return state
}
export {
    aa
}

index.js进行数据监听

// 操作dom
import ReactDOM from "react-dom/client";
// 引入App组件
import App from "./App"
// 引入css文件
import "./app.scss"
import store from "./redux/store"

import { BrowserRouter } from "react-router-dom"
// 设置挂载位置
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(
    <App />
)
store.subscribe(() => {
    root.render(
        <App />
    )
})

5.一个基础完整的redux实例代码

App.js

import React from 'react'
import store from "./redux/store"
import { createAdd, createDel } from './redux/action/createSum'
export default function App() {
    let { num } = store.getState()
    const handleAdd = () => {
        store.dispatch(createAdd())
    }
    const handleDel = () => {
        store.dispatch(createDel())
    }
    return (
        <div>
            <p>数据之{num}</p>
            <button onClick={handleAdd}>Add1</button>
            <button onClick={handleDel}>Del1</button>
        </div>
    )
}

redux/action/createSum.js

export const createAdd = () => {
    return { type: 'add', data: 1 }
}
export const createDel = () => {
    return { type: 'del', data: 1 }
}

redux/store.js

import { createStore } from 'redux'
import { aa } from './reducer/reducers'
export default createStore(aa)

redux/reducer/reducers.js

let init = { num: 1 }
function aa(state = init, actions) {
    console.log(state, actions);
    //由于纯函数的规范,返回是新的值
    let newState = { ...state }


    switch (actions.type) {
        case "add":
            newState.num = newState.num + actions.data
            return newState
        case "del":
            newState.num -= actions.data
        default:
            break;
    }
    return newState
}
export {
    aa
}

6.redux store里面处理异步

需要引入插件 redux-thunk

在store.js中引入

import { createStore, applyMiddleware } from 'redux'
import { aa } from './reducer/reducers'
import reduxThunk from 'redux-thunk'
export default createStore(aa, applyMiddleware(reduxThunk))

7.react-redux

小分类?

react-redux 旧版本 函数与class都通用

react-toolkit hooks版本,函数用的

什么是react-redux?

​ redux是一个独立的仓库,可以和市面上流行的框架例如Vue,angular,react等ui框架结合一起使用。如果我们要同时使用react和redux的时候,我们建议不要直接把react组件内容和store进行交互,而是应该将react-redux作为中间桥梁连接其中。

在这里插入图片描述

  1. 容器组件 包裹 UI组件 通过容器组件 与 redux进行操作
  2. 容器组件操作仓库 仓库数据给容器组件, 容器组件将数据给UI组件
  3. UI组件触发 容器组件发送action 给仓库进行修改数据

使用:

安装

npm i react-redux

初始版本:

components/SumUI

import React from 'react'
import store from "../redux/store"
import { createAdd, createDel, createAsync } from '../redux/action/createSum'
export default function SumUI(props) {
    console.log(props);
    let num = props.num
    const handleAdd = () => {
        props.handleAdd()
    }
    const handleDel = () => {
        props.handleDel()
    }
    const handleAsync = () => {
        props.handleAsync()
    }
    return (
        <div>
            <p>数据之{num}</p>
            <button onClick={handleAdd}>Add1</button>
            <button onClick={handleDel}>Del1</button>
            <button onClick={handleAsync}>异步加</button>
        </div>
    )
}

containner/Sum

import { connect } from 'react-redux'
import SumUI from '../component/SumUI'
import { createAdd, createDel, createAsync } from '../redux/action/createSum'
function mapStateToProps(state) {
    return state
}
const mapDispatchToProps = (dispatch) => {

    return {
        handleAdd: () => dispatch(createAdd()),
        handleDel: () => dispatch(createDel()),
        handleAsync: () => dispatch(createAsync())
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(SumUI)

App.js

import React from 'react'
import Sum from './container/Sum'
import store from './redux/store'
export default function App() {
    return (
        <div>
            <Sum store={store}></Sum>
        </div>
    )
}

优化点:

1.mapStateToProps直接在connect里面写回调函数

2.mapDispatchToProps可以写成对象形式。系统会自动用dispatch包裹。

Sum.jsx优化

import { connect } from 'react-redux'
import SumUI from '../component/SumUI'
import { createAdd, createDel, createAsync } from '../redux/action/createSum'


export default connect(state => state, {
    handleAdd: createAdd,
    handleDel: createDel,
    handleAsync: createAsync
})(SumUI)

8.多组件之间通信

关键api:combineReducer

9.使用redux-devtools

如果要使用redux-devtools,我们需要使用第三方插件

安装 redux-devtools-extension,然后在store.js中配置

import {applyMiddleware, createStore,combineReducers} from "redux"
// 引入stroe异步中间件
import Thunk from "redux-thunk"
// 引入所有的纯函数reduce
import reduce from "./index"
// 使用插件查看数据
import {composeWithDevTools} from "redux-devtools-extension"
// 暴露仓库(store)
export default createStore(reduce,composeWithDevTools(applyMiddleware(Thunk)))

10.react-redux提供自定义的hooks

需要三个 redux react-redux @reduxjs/toolkit

1.创建store redux/store.js

// 开始准备创建仓库
import { configureStore } from '@reduxjs/toolkit';
// 引入纯函数
import reducerSum from "./reducers/reduceSum"


// 返回值就是仓库
const store = configureStore({
    // 每个组件的纯函数
    reducer:{
        reducerSum
    }
})



export default store

2.创建reducer纯函数 reducers/reduceSum.js

// 通过@reduxjs/toolkit创建纯函数
import {createSlice} from "@reduxjs/toolkit"

// 创建纯函数
const  reducerSum =  createSlice({
    name:"reducerSum",  // 名称
    initialState:{     // 初始数据 对象
        num:0,
        qwe:"大哥"
    },
    reducers:{          // 重新处理数据
        ADD:(state,action)=>{       // 数据加
            console.log(action);
            // state 代表数据原
            state.num = state.num +  action.payload
        },
        Reduce:(state,action)=>{
            state.num = state.num -  action.payload
        },
    }      
})

console.log(reducerSum,123);
export const {ADD,Reduce} = reducerSum.actions;  // 暴露行为给组件调用
export default reducerSum.reducer;  // 暴露reduce纯函数给仓库store

组件使用数据

import { useStore, useSelector, useDispatch } from "react-redux"
import { Reduce } from "../redux/reducers/reduceSum"


export default function Sum() {
    const store = useStore()
    console.log(store.getState().reducerSum.num,"useStore");

    const {num,qwe} = useSelector((state)=>state.reducerSum)
    console.log(num,"num");

    const dispatch = useDispatch()

    const handlAdd = ()=>{
        // dispatch({type: 'reducerSum/ADD',payload:1})
        // ADD(123)
        // dispatch(ADD(123)) 
    }

    const handlreduc = ()=>{
        dispatch(Reduce(10))
    }
  return (
    <div>
        <p>Sum--{store.getState().reducerSum.num}</p>
        <p>{num}--{qwe}</p>
        <button onClick={handlAdd}>点击夹</button>
        <button onClick={handlreduc}>点击减</button>

    </div>
  )
}

书写redux的规范

1.纯函数不要返回修改上一次的state数据,建议复制一下数据,然后进行修改,再进行返回数据

/ dispatch({type: ‘reducerSum/ADD’,payload:1})
// ADD(123)
// dispatch(ADD(123))
}

const handlreduc = ()=>{
    dispatch(Reduce(10))
}

return (


Sum–{store.getState().reducerSum.num}


{num}–{qwe}


点击夹
点击减

</div>

)
}






## 书写redux的规范

> 1.纯函数不要返回修改上一次的state数据,建议复制一下数据,然后进行修改,再进行返回数据
>
> 2.reducer不要执行任何异步操作,仅仅修改数据,赋值就好了。负责修改state数据
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值