react17--redux入门


1、流程


先看张redux工作流程图
在这里插入图片描述

刚开始看我也有点懵,把他比喻成生活中的一个小例子就好理解了,比如图书馆借书的例子:

首先简单的把components比做成借书的人

当借书人(components)说:我要借书,那么说话的这个行为就是actions

这时候图书管理员(Store)听见了,他来集中管理书籍的信息、数据

图书管理员(Store)也不知道你要借哪一本书、有没有这本书,他要求查一下,看下手册(reducers),
最后告诉管理员(Store)关于这本书的数据信息

1、首先我们的组件要访问Store里面的数据,这时候要获取数据的这个行为就会触发Action Creators

​2、随后Action Creators通过一些其他的function告诉Store要获取某些数据,这时候Store也不知道要获取哪些数据

​3、这时候Reducers查一下并告诉Store要返回哪些数据给组件,Store知道后把数据返回给Components


2、入门使用


创建store.js和reducer.js
在这里插入图片描述

store.js代码

import { createStore } from 'redux'
import Reducer from './reducer'

// window下有这个变量则执行调试工具
const Store = createStore(
    Reducer, /* preloadedState, */
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  )

export default Store

reducer.js代码

const defaultState = {
    inputVal: '666',
    list: [1,2,3]
}

// reducer中需要返回一个函数,接收旧的 state 和 action,返回新的 state
//reducer可以接收state,但是不能修改state
export default (state = defaultState, action) => {
    return state
}

然后在页面中引入store

import Store from '../store'

通过getState()来获取Store中的数据
通过subscribe()在组件内更新Store
通过dispatch()将修改后的数据传给Store

import React, { Component } from 'react'
import Store from '../store'
import { Button, Input, List } from 'antd'



export default class TodoList extends Component {
    constructor(props){
        super(props)
        let { list, inputVal } = Store.getState()
        this.state = {
            list, inputVal
        }
        
    }
    render() {
        const { list, inputVal } = this.state
        return (
            <div>
                <h1>rodolist</h1>
                <Input value={inputVal} placeholder="Basic usage" style={{width:'300px'}} />
                <Button type="primary">Primary Button</Button>
                <List
                    size="default"
                    bordered
                    dataSource={list}
                    renderItem={item => <List.Item>{item}</List.Item>}
                />
            </div>
        )
    }
}

在这里插入图片描述

现在我们想在输入框中输入一条数据点击按钮添加到列表中,上代码

todoList.js

import React, { Component } from 'react'
import Store from '../store'
import { Button, Input, List } from 'antd'



export default class TodoList extends Component {
    constructor(props){
        super(props)
        //利用getState()获取store中的数据
        // console.log(Store.getState())
        let { list, inputVal } = Store.getState()
        this.state = {
            list, inputVal
        }
    }
    componentDidMount(){
        //store发生变化就更新
        Store.subscribe(this.handleStoreChange)
    }
    componentDidUpdate(){
        Store.subscribe(this.handleStoreChange)
    }
    handleInputChange(e){
        const action = {
            type: 'changeInputVal',
            value: e.target.value
        }
        //将修改后的数据传给store
        Store.dispatch(action)
    }
    handleStoreChange = () => {
        let tVal = Store.getState()
        console.log('tVal',tVal)
        this.setState({
            inputVal: tVal.value,
            list: tVal.list
        })
    }
    onClickSubmit = () => {
        const { inputVal } = Store.getState()
        console.log(inputVal)
        //为空不添加
        if (!inputVal) return
        const action = {
            type: 'addItem'
        }
        Store.dispatch(action)
        this.setState({
            inputVal: ''
        })
    }
    render() {
        const { list, inputVal } = this.state
        return (
            <div>
                <h1>rodolist</h1>
                <Input value={inputVal} onChange={(e) => this.handleInputChange(e)} placeholder="Basic usage" style={{width:'300px'}} />
                <Button type="primary" onClick={() => this.onClickSubmit()}>Primary Button</Button>
                <List
                    size="default"
                    bordered
                    dataSource={list}
                    renderItem={item => <List.Item>{item}</List.Item>}
                />
            </div>
        )
    }
}

完整reducer.js代码

const defaultState = {
    inputVal: '666',
    list: [1,2,3]
}

// reducer中需要返回一个函数,接收旧的 state 和 action,返回新的 state
export default (state = defaultState, action) => {
    console.log('action',action)
    if (action.type === 'changeInputVal') {
        //reducer可以接收state,但是不能修改state;所以要进行一次深拷贝
        let newState = JSON.parse(JSON.stringify(state))
        newState.inputVal = action.value
        return newState
    }
    if (action.type === 'addItem') {
        let newState = JSON.parse(JSON.stringify(state))
        newState.list.push(newState.inputVal)
        newState.inputVal = ''
        console.log('newState',newState)
        return newState
    }
    return state
}

在调试工具中看到数据也是正确的
在这里插入图片描述
在这里插入图片描述


3、Action代码拆分、优化


回头看一下写的代码,我自己看着都难受;考虑到以后万一action很多呢,那不是要累死;还有另一种情况:万一type名称拼写错了,也要找半天,所以这样是不可取的应该拆分出来
在这里插入图片描述

拆分之前先来分析应该要怎么拆分?
我们可以看到每一个action都有一个type、value;然后reducer里面都会有对应的逻辑处理,根据这两点就容易多了
继续在store目录下新建两个文件
在这里插入图片描述

actionTypes.js

export const changeInputVal = 'changeInputVal'

export const addItem = 'addItem'

export const deleteItem = 'deleteItem'

actionCreators.js

import { changeInputVal, addItem, deleteItem } from './actionTypes'

export const getInputChangeAction = (value) => ({
    type: changeInputVal,
    value
})

export const getOnSubmitAction = () => ({
    type: addItem
})

export const getDeleteItemAction = (index) => ({
    type: deleteItem,
    index
})

reducer.js代码

import { changeInputVal, addItem, deleteItem } from './actionTypes'
const defaultState = {
    inputVal: '',
    list: []
}

export default (state = defaultState, action) => {
    if (action.type === changeInputVal) {
        let newState = JSON.parse(JSON.stringify(state))
        newState.inputVal = action.value
        return newState
    }
    if (action.type === addItem) {
        let newState = JSON.parse(JSON.stringify(state))
        newState.list.push(newState.inputVal)
        newState.inputVal = ''
        return newState
    }
    if (action.type === deleteItem) {
        let newState = JSON.parse(JSON.stringify(state))
        newState.list.splice(action.index,1)
        return newState
    }
    return state
}

在todolist引入
如果方法少可以这样,多的话直接import * as xxxx from xxxxxx

import { getInputChangeAction, getOnSubmitAction, getDeleteItemAction } from '../store/actionCreators'

直接在对应的方法下调用并传参即可

onClickSubmit = () => {
        const action = getOnSubmitAction()
        Store.dispatch(action)
}
handleInputChange(e){
        const action = getInputChangeAction(e.target.value)
        Store.dispatch(action)
}
deleteItem = (index) => {
        Store.dispatch(getDeleteItemAction(index))
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值