[React] 14 - Redux: add more components

基本开发流程 (针对一个组件)

 

  • 第二步

he的初始值;this.add调用的对应方法jiafa;

注意:createIncrementAction 是action中在定义(了个“dict")

state, createIncrementAction的具体操作则都在reducer中提前定义好。

    //加法
    increment = ()=>{
        const {value} = this.selectNumber
        this.props.jia(value*1)
    }
add method 实现

 

 

  

添加 Person 组件

./redux/actions/xxx.js
./redux/reducers/xxx.js

 

[第一步] 先各自定义两个 “独立” 的部分:UI 与 逻辑。

 

    • 定义好了 “UI部分”

注意:state部分 是与Count 共享了 he这个状态。毕竟大家都用着同一个store。

containers/Person/index.jsx

class Person extends Component { addPerson_onClick
= ()=>{ const name = this.nameNode.value const age = this.ageNode.value
const
personObj = {id:nanoid(), name, age}
this.props.
jiaYiRen(personObj) } render() { return ( <div> <h2>我是Person组件,上方组件求和为{this.props.he}</h2>  // <------- 共享的部分~ <input ref={c=>this.nameNode = c} type="text" placeholder="输入名字"/> <input ref={c=>this.ageNode = c} type="text" placeholder="输入年龄"/> <button onClick={this.addPerson_onClick}>添加</button> <ul> { this.props.yiduiren.map((p)=>{ return <li key={p.id}>{p.name}--{p.age}</li> }) } </ul> </div> ) } }
// 以上应该没任何 redux 东西,只专注于 UI部分~
export
default connect( state => ({yiduiren:state.rens, he:state.he}), // 映射状态 --> mapStateToProps {jiaYiRen:createAddPersonAction} // 映射操作状态的方法 --> mapDispatchToProps(需在下一步定义createAddPersionAction的format) )(Person)

 

    •  定义好了 “逻辑部分”

重点理解:上面的 createAddPersonAction 定义好了 “数据包”;但这个包如何传递到下面的 persionReducer's parameter?

redux/reducers/person.js

import {ADD_PERSON} from '../constant' //初始化人的列表 const initState = [{id:'001',name:'tom',age:18}] export default function personReducer(preState=initState, action){ // console.log('personReducer@#@#@#'); const {type, data} = action switch (type) { case ADD_PERSON: return [data,...preState] // ----> 纯函数 default: return preState } }
import {INCREMENT,DECREMENT} from '../constant'

const initState = 0 //初始化状态
export default function countReducer(preState=initState,action){
    // console.log('countReducer@#@#@#');
    //从action对象中获取:type、data
    const {type,data} = action
    //根据type决定如何加工数据
    switch (type) {
        case INCREMENT: //如果是加
            return preState + data
        case DECREMENT: //若果是减
            return preState - data
        default:
            return preState
    }
}
redux/reducers/count.js
7.8.1. 纯函数
一类特别的函数: 只要是同样的输入(实参),必定得到同样的输出(返回)

必须遵守以下一些约束  

不得改写参数数据

不会产生任何副作用,例如网络请求,输入和输出设备

不能调用Date.now()或者Math.random()等不纯的方法  

redux的reducer函数必须是一个纯函数

7.8.2. 高阶函数
理解: 一类特别的函数

情况1: 参数是函数

情况2: 返回是函数

常见的高阶函数:

定时器设置函数

数组的forEach()/map()/filter()/reduce()/find()/bind()

promise

react-redux中的connect函数

作用: 能实现更加动态, 更加可扩展的功能
纯函数和高阶函数

 

[第二步] 作为“粘和”,这需要定义 消息的格式,以及调度者也需支持这个格式。

 

    • action

UI组件 涉及的两个地方,其中之一就是简单的定义了action 的消息格式,在如下定义。

./redux/actions/person.js

import {ADD_PERSON} from '../constant' //创建增加一个人的action动作对象 export const createAddPersonAction = personObj => ({type:ADD_PERSON, data:personObj})
/* 
    该文件专门为Count组件生成action对象
*/
import {INCREMENT,DECREMENT} from '../constant'

//同步action,就是指action的值为Object类型的一般对象
export const createIncrementAction = data => ({type:INCREMENT,data})
export const createDecrementAction = data => ({type:DECREMENT,data})

//异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的。
export const createIncrementAsyncAction = (data,time) => {
    return (dispatch)=>{
        setTimeout(()=>{
            dispatch(createIncrementAction(data))
        },time)
    }
}
./redux/actions/count.js

 

    • store

另一部分的state定义在reducer中。Why? 因为reducer中定义了 initState。指定了reducer,也就是指定了state

./redux/store.js

//
汇总所有的reducer变为一个总的reducer const allReducer = combineReducers({ he:countReducer, rens:personReducer }) //暴露store export default createStore(allReducer, applyMiddleware(thunk))

 

 

 

Redux Tool

npm install --save-dev redux-devtools-extension
//引入redux-devtools-extension
import {composeWithDevTools} from 'redux-devtools-extension'

//汇总所有的reducer变为一个总的reducer
const allReducer = combineReducers({
    he:countReducer,
    rens:personReducer
})

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

安装包,并引用。

 

 

 

 

大总结


各个注意点

1. 用Provider包裹App,目的是让App所有的后代容器组件都能接收到store。

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')
)
./index.js

 

2. 引入的是“容器组件”,而非UI组件。

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>
        )
    }
}
./App.jsx

 

3. 采用js对象的简写方式。

./containers/Person/index.js

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_onClick = ()=>{ 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_onClick}>添加</button> <ul> { this.props.persons.map((p)=>{ return <li key={p.id}>{p.name}--{p.age}</li> }) } </ul> </div> ) } } export default connect( state => ({ persons:state.persons, count:state.count }), // 映射状态 {addPerson} // 映射操作状态的方法 )(Person)

 

4. store引入一个 "作为汇总的reducer“ 即可。

./redux/reducers/index.js

import count from './count' import persons from './person' //汇总所有的reducer变为一个总的reducer export default combineReducers({ count, persons })

 

posted @ 2018-05-20 20:21  郝壹贰叁  阅读(359)  评论(0编辑  收藏  举报