redux和react-redux快速入门

一、redux

1. 导包

npm i redux 
// 或 
yarn add redux

2. 创建store(仓库)和reducer(仓库管理员)

src/store/reducer.js

const defaultState = {
    num: 0 // 初始化一个数据
}
// 导出一个函数(仓库,动作)
export default (state = defaultState, action) => {
    return state
}

src/store/index.js

import { legacy_createStore as createStore } from "redux";
import redurce from "./redurce";
export default createStore(redurce)

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
}

src/App.jsx

import React, { useEffect, useState } from 'react'
// 导入 store 仓库
import store from '../store'

export default function App() {
  return (
	<div>
		// store.getState()获取store的值
		<h2>{ store.getState().num }</h2>
		// 定义一个add累加方法
      	<button onClick={() => add(2)}>+</button>
    </div>
  )
  
  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({})
    })
  })
  
}

**注意:**redux中,当store数据更新后,界面数据并不会直接更新,需要手动更新

如果是函数式组件,手动更新方式如上

类式组件,使用生命周期直接在store.subscribe()中调用setState()即可实现更新数据

componentDidMount() {
    store.subscribe(() => {
      this.setState({})
    })
  }

二、react-redux(todo案例)

1. 导入依赖

redux和react-redux
还有antd

yarn add redux react-redux antd

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传进来
      <Provider store={store}>
          <App />
      </Provider>
  </React.StrictMode>
)

src/store/constant.ts

用来存储action对象的type属性

export const AddTodo = 'ADD_TODO'

src/store/index.ts

import { legacy_createStore as createStore } from "redux";
import reducer from "./reducer";
export default createStore(reducer)

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
}

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 (
        <div className='todo_container'>
            <div className="todo">
                <div className="top">
                    <Input placeholder="Basic usage" value={inputTodo} onChange={(e) => setInputTodo(e.target.value)} />
                    <Button onClick={addTodo} style={{marginLeft: '10px'}} type="primary">提交</Button>
                </div>
                <List
                    size="large"
                    bordered
                    dataSource={data}
                    renderItem={item => {
                        // @ts-ignore
                        return <List.Item>{item.name}</List.Item>
                    }}
                />
            </div>
        </div>
    )

}
// 状态映射
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)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值