一、redux
- 导包 npm i redux // 或 yarn add redux 1 2 3
- 创建store(仓库)和reducer(仓库管理员) src/store/reducer.js
const defaultState = { num: 0 // 初始化一个数据 } // 导出一个函数(仓库,动作) export default (state = defaultState, action) => { return state } 1 2 3 4 5 6 7 src/store/index.js
import { legacy_createStore as createStore } from "redux"; import redurce from "./redurce"; export default createStore(redurce) 1 2 3 3. 组件中使用redux src/store/reducer.js
在reducer中定义一个事件,让组件来触发,以修改store
const defaultState = { num: 0 } export default (state = defaultState, action) => { // 将type和data从action对象中解构出来,方便后面使用 const {type, data} = action; // 如果action的type为add,这执行此代码,返回新的store数据 if(type === 'add') { // store的num累加传过来的数值 state.num += data; // 需要深拷贝,返回新的state数据 let newState = JSON.parse(JSON.stringify(state)) return newState; } // 默认返回原state对象 return state } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 src/App.jsx
import React, { useEffect, useState } from 'react' // 导入 store 仓库 import store from '../store'
export default function App() { return (
{ store.getState().num }
// 定义一个add累加方法 <button onClick={() => add(2)}>+const add = (data) => { // store.dispatch()来触发reducer中的事件,修改store // 需要传一个action对象,格式为 {type: name, data: xx} // action对象的type属性需要和reducer中action对应type一致 store.dispatch({ type: 'add', data }) }
// 大坑:redux中,当store数据更新后,界面数据并不会直接更新,需要手动更新 // 初始化一个update数据使用useState(),主要是为了通过setUpdate()来更新组件 // 模拟render()生命周期,实现组件重新加载,以更新界面的store数据 const [update,setUpdate] = useState({})
// useEffect模拟componentDidMount()生命周期 useEffect(() => { // store.subscribe()是redux提供的,监测store更新的函数 store.subscribe(() => { // 当store数据更新后执行 setUpdate() ,组件重新加载,实现界面store数据更新 setUpdate({}) }) })
} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 **注意:**redux中,当store数据更新后,界面数据并不会直接更新,需要手动更新
如果是函数式组件,手动更新方式如上
类式组件,使用生命周期直接在store.subscribe()中调用setState()即可实现更新数据
componentDidMount() { store.subscribe(() => { this.setState({}) }) } 1 2 3 4 5 二、react-redux(todo案例)
- 导入依赖 redux和react-redux 还有antd
yarn add redux react-redux antd 1 2. code main.tsx
import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import 'antd/dist/antd.css' // 导入Provider从react-redux中 import {Provider} from "react-redux" // 导入store import store from "./store";
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( <React.StrictMode> // 使用Provider组件包嵌套需要使用store的组件 // 并且将store传进来 </React.StrictMode> ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 src/store/constant.ts
用来存储action对象的type属性
export const AddTodo = 'ADD_TODO' 1 src/store/index.ts
import { legacy_createStore as createStore } from "redux"; import reducer from "./reducer"; export default createStore(reducer) 1 2 3 src/store/reducer.ts
import {AddTodo} from "./constant"; const defaultState = { // 初始化数据 todo: [ { id: '001', name: 'code' }, { id: '002', name: 'sleep' } ] }
export default (state = defaultState, action: {type: string, data?:any}) => { const {type, data} = action switch (type) { case AddTodo: state.todo.unshift(data) return JSON.parse(JSON.stringify(state)) default: return state } return state } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 src/component/Todo/index.tsx
import { Button, Input, List, message } from 'antd' import './index.less' import {connect} from "react-redux"; import {useState} from "react"; import {AddTodo} from "../../store/constant"; import { nanoid } from 'nanoid'
function index(props: any) { const data = props.todo const [inputTodo, setInputTodo] = useState(''); const addTodo = () => { if(inputTodo.trim() === '') { return message.info('请输入人内容'); } props.addTodo({ id: nanoid(), name: inputTodo }) } return (
} // 状态映射 const mapStateToProps = (state: any) => { return { todo: state.todo } }
// 事件派发映射 const mapDispatchToProps = (dispatch: {type:string, data: any}) => { return { addTodo(data: any) { // @ts-ignore dispatch({ type: AddTodo, data }) } } } // @ts-ignore export default connect(mapStateToProps, mapDispatchToProps)(index) ————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。