React learning 29 (react-redux final full version)

illustrate

1) All variable names should be standardized, try to trigger the abbreviation of the object

2) In the reducers folder, write index.js specifically for summarizing and exposing all reducers

project structure

 

code example

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App.jsx'
import store from './redux/store'//为provider服务
import {Provider} from 'react-redux'

ReactDOM.render(
  //此处需要用provider包裹App,目的是让App所有的后代容器组件都能够接收到store
<Provider store= {store}>
  <App/>
</Provider>,
document.getElementById('root')
)

App.jsx

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>
    )
  }
}

redux-store.js

/*
  该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/

//引入createStore,专门用于创建redux中最为核心的store对象,applyMiddleware用于支持
//异步action的中间件
//combineReducers用于合并多个reducer
import {createStore,applyMiddleware} from 'redux'

//引入汇总之后的reducers
import reducer from './reducers'

//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'

//引入redux-devtools-extension
import {composeWithDevTools} from 'redux-devtools-extension'

export default createStore(reducer, composeWithDevTools(applyMiddleware(thunk)))

redux-constant.js

/*
  该文件是用于定义action对象中的type类型的常量值
  目的只有一个:防止程序员在编码的同时单次写错
*/

export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
export const ADD_PERSON = 'add_person'

redux-reducers-index.js

/*
  该文件用于汇总会有的reducer为一个总的reducer
*/
//引入combineReducers,用于汇总多个reducer
import {combineReducers} from 'redux'

//引入为Count组件服务的reducer
import count from './count'

//引入为Person组件服务的reducer
import persons from './person'

//汇总所有的reducer变为一个总的reducers 
export default combineReducers({
  count,
  persons
})

redux-reducers-count.js

/*
  1.该文件用于创建一个为count组件服务的reducer,reducer的本质就是一个函数
  2.reducer函数会接到两个参数,分别是之前的state(状态)和action(动作对象)
*/
import { INCREMENT, DECREMENT } from "../constant";

const initState = 0
export default function countReducer(preState=initState, action) {
  console.log(preState, action);
  //从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-person.js

import { ADD_PERSON } from "../constant"

//初始化人的列表
const initState = [{id:'001',name:'tom', age:18}]

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

redux-actions-count.js

/*
  该文件专门为count组件生成action对象
*/
import { INCREMENT, DECREMENT } from "../constant"
//完整写法
// function createIncrementAction(data) {
//   return {type:'increment', data }
// }
//简写形式
//同步action,就是值action的返回值是Object类型的一般对象
export const increment = data =>( {type:INCREMENT, data })

//完整写法
// function createDecrementAction(data) {
//   return {type:'decrement', data}
// }
export const decrement = data =>( {type: DECREMENT, data })

//异步action,就是值action的返回值是函数,异步action一般都会调用同步action
//异步action不是必须要用的
export const incrementAsync = (data, time) =>{
  return (dispatch) => {
    setTimeout(() => {
      dispatch(increment(data))
    },time)
  }
}

redux-actions-person.js

import {ADD_PERSON} from '../constant'

//创建增加一个人的action对象
export const addPerson = personObj => ({type:ADD_PERSON, data:personObj})

container-count-index.jsx

//引入CountUI组件
// import CountUI from '../../compoents/Count'

import React, { Component } from 'react'

//引入connect用于连接UI组件和redux
import {connect} from 'react-redux'
//引入action
import {
  increment,
  decrement,
  incrementAsync
} from '../../redux/actions/count'

//定义UI组件
class Count extends Component {
  state = {carName:'奔驰c63'}//  把状态交给reducer之后组件也可以有自己独用的状态


  increment = () => {
    const {value} = this.selectNum
    this.props.increment(value*1)

  }
  decrement = () => {
    const {value} = this.selectNum
    this.props.decrement(value*1)
  }
  incrementOdd = () => {
    const {value} = this.selectNum
    if(this.props.count % 2 !== 0) {
      this.props.increment(value*1)
    }
  }
  incrementWait = () => {
    const {value} = this.selectNum
    this.props.incrementAsync(value*1,400)
  }
  render() {
    console.log('UI组件接收到的props是:',this.props);
    return (
      <div>
        <h2>我是Count组件,下方组件总人数是:{this.props.personCount}</h2>
        <h3>当前求和为:{this.props.count}</h3>
        <select ref={c => {this.selectNum = 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.incrementOdd}>当前求和为奇数再加</button>&nbsp;
        <button onClick= {this.incrementWait}>等一等再加</button>
      </div>
    )
  }
}

//使用connect()()创建并暴露一个Count容器组件
export default connect(
  state => ( {
    count:state.count,
    personCount:state.persons.length
  }), 
  //mapDispatchToProps的一般写法
  // dispatch => ({
  //   jia:number => dispatch(createIncrementAction(number)),
  //   jian:number => dispatch(createDecrementAction(number)),
  //   jiaAsync:(number,time) =>dispatch(createIncrementAsyncAction(number,time)) 
  // })

   //mapDispatchToProps的简写,dispatch由react-redux来完成,程序员工作中用这种方法
   {
    increment,
    decrement,
    incrementAsync
   }
  )(Count)

container-person-index.jsx

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
    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="请输入姓名"/>&nbsp;
        <input ref={c => this.ageNode = c} type="text" placeholder="请输入年龄"/>&nbsp;
        <button onClick= {this.addPerson}>添加</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)

Guess you like

Origin blog.csdn.net/xiaojian044/article/details/128360529