likes
comments
collection
share

随便写写之实现一个react-redux的简单demo

作者站长头像
站长
· 阅读数 66

react-redux其实就是对redux进行基于react框架的进一步的封装,其底层核心还是使用的redux原理。结合如下流程图,我们先用react-redux来实现本文的小例子来看下react-redux 的具体使用,此文适合初学者。 随便写写之实现一个react-redux的简单demo

Provider

react-redux 提供了一个Provider组件,该组件可以将store提供给所有的子组件使用,其利用的是react的context属性实现,具体使用方法如下:

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import store from './redux/store'
import { Provider } from 'react-redux'

ReactDOM.render(
    /* 此处用Provider包裹App,目的是让App所有的子容器组件都能接收到 store信息 */
    <Provider store={store}>
       <App/>
    </Provider>,
    document.getElementById('root')

// 在app容器组件中,通过引入两个子容器组件 Count、Person,并通过这两个组件之间的交互来实现本文的效果
import React, { Component } from 'react'
import Count from './containers/Count' // 引入的Count的容器组件
import Person from './containers/Person' // 引入的Person的容器组件

export default class App extends Component {
    render() {
        return (
            <div>
                <Count/>
                <hr/>
                <Person/>
            </div>
        )
    }
}

如上所示,我们在入口文件index.js引入Providerstore;然后利用Providerstore注入到所有的子组件中,这样所有的子组件就就可以拿到 store 了。该特性利用的是react的context属性,相当于将 store数据共享给所有的子容器组件。

store

首先,在核心文件 store.js 中,通过redux提供的createStore创建一个store实例,createStore接收一个reducer函数作为参数,第二个参数用来支持异步action。

// 引入createStore创建redux中最为核心的store对象; applyMiddleware用来支持异步action的中间件
import { createStore, applyMiddleware } from 'redux'
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
// 引入redux-devtools-extension
import { composeWithDevTools } from 'redux-devtools-extension'
// 引入combineReducers,用于汇总多个reducer
import { combineReducers } from 'redux'

// 引入所有的 reducer
import count from './reducers/count'
import persons from './reducers/person'

// 引入所有的reducer变为一个总的reducers
const allReducer = combineReducers({
  count,
  persons
})

//暴露store 
export default createStore( allReducer, composeWithDevTools(applyMiddleware(thunk)))

创建action和reducer

如下图是actionreducer绑定后的数据交互图,可以很好的解释上图中的右边部分。在视图组件中通过dispatch 发起动作对象 action, 同时reducer函数会接到两个参数,分别为:之前的状态 preState ,动作对象action,在reducer函数里面通过action对象中的type类型来执行对应的操作,得到最新的state 数据。流程如下图所示: 随便写写之实现一个react-redux的简单demo

继续实现上述的demo的action:

// 该文件专门为Count组件生成action对象
export const increment = data => ({type: 'increment', data})
export const decrement = data => ({type: 'increment', data})

//异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的。
export const incrementAsync = (data,time) => {
    return (dispatch)=>{
        setTimeout(()=>{
                dispatch(increment(data))
        },time)
    }
}
// 该文件专门为Person组件生成action对象
export const addPerson = personObj => ({type: 'addPerson',data: personObj})

继续实现上述的demo的 reducer:

// 1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
// 2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
const initState = 0 //初始化状态
export default function countReducer(preState = initState, action){
    //从action对象中获取:type、data
    const { type, data } = action
    switch (type) {
        case 'increment': // 如果是加
            return preState + data
        case 'decrement': // 如果是减
            return preState - data
        default:
            return preState
    }
}
// 该文件是用于创建一个为 Person 组件服务的reducer
const initState = [{ id:'8', name:'kobe', age:24 }]

export default function personReducer(preState = initState, action){
    const {type,data} = action
    switch (type) {
        case 'addPerson': //若是添加一个人
            return [data,...preState]
        default:
            return preState
    }
}

子容器组件的实现

// Count 组件的实现
import React, { Component } from 'react'
import { increment, decrement, incrementAsync } from '../../redux/actions/count'
import {connect} from 'react-redux'

//定义UI组件
class Count extends Component {
    //加法
    increment = ()=>{
        const {value} = this.selectNumber
        this.props.increment(value*1)
    }
    //减法
    decrement = ()=>{
        const {value} = this.selectNumber
        this.props.decrement(value*1)
    }
    //奇数再加
    incrementIfOdd = ()=>{
        const {value} = this.selectNumber
        if(this.props.count % 2 !== 0){
            this.props.increment(value*1)
        }
    }
    //异步加
    incrementAsync = ()=>{
        const {value} = this.selectNumber
        this.props.incrementAsync(value*1,500)
    }

    render() {
        return (
            <div>
                {/* 此处可以取到其他组件的state数据 */}
                <h2>我是Count组件,下方组件总人数为:{this.props.personCount</h2>
                <h4>当前求和为:{this.props.count}</h4>
                <select ref={c => this.selectNumber = c}>
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                </select>&nbsp;
                <button onClick={this.increment}>+</button>&nbsp;
                <button onClick={this.decrement}>-</button>&nbsp;
                <button onClick={this.incrementIfOdd}>当前求和为奇数</button>&nbsp;
                <button onClick={this.incrementAsync}>异步加</button>&nbsp;
            </div>
        )
    }
}

// 使用connect()()创建并暴露一个Count的容器组件
export default connect(
    state => ({
        count: state.count,
        personCount: state.persons.length
    }),
    {increment, decrement, incrementAsync}
)(Count)
// Person 组件的实现
import React, { Component } from 'react'
import {nanoid} from 'nanoid'
import {connect} from 'react-redux'
import {addPerson} from '../../redux/actions/person'

class Person extends Component {
    addPerson = ()=>{
        const name = this.nameNode.value
        const age = this.ageNode.value*1
        const personObj = {id:nanoid(),name,age}
        this.props.addPerson(personObj)
        this.nameNode.value = ''
        this.ageNode.value = ''
    }

    render() {
        return (
            <div>
                <h2>我是Person组件,上方组件求和为{this.props.count}</h2>
                <input ref={c=>this.nameNode = c} type="text" placeholder="输入名字"/>
                <input ref={c=>this.ageNode = c} type="text" placeholder="输入年龄"/>
                <button onClick={this.addPerson}>添加</button>
                <ul>
                    {
                        this.props.persons.map((p)=>{
                             return <li key={p.id}>{p.name}--{p.age}</li>
                        })
                    }
                </ul>
            </div>
        )
    }
}

// 使用connect()()创建并暴露一个Person的容器组件
export default connect(
    state => ({
        persons:state.persons,
        count:state.count
    }),
    {addPerson}
)(Person)
转载自:https://juejin.cn/post/7270829679087091772
评论
请登录