第七章:redux

目录

 

一、redux简介

1.学习文档

 2.redux是什么,什么时候使用

二、redux精简版(实现求和案例)

1.在src目录下新建一个redux文件夹:

三、redux完整版(实现求和案例)

1.在src目录下新建一个redux文件夹:

2.使用Count.vue:

四、异步action版本(不一定需要使用)

1.同步与异步的区别:

1.在src目录下新建一个redux文件夹:

2.Count.vue使用

五、react-redux官方推荐

​编辑 1.新建一个container文件夹在下面在新建一个Count的组件作为CountUI组件的容器组件

2.在App.jsx里面导入的Count容器组件,并传入store

3.component/Count/index.jsx使用

4.redux文件与上面的是一样的

六、react-redux的优化

1.根目录的index.js文件:利用provide向全局提供store

2.App.js文件不需要传递store

3.container/Count/index.js下面的写法

4.redux其他代码没变

七、react-redux的数据共享(正式开发)

1.redux文件夹里面分别新建reducers文件夹与actions文件夹和store.js和constant.js文件夹

2.使用:新建container文件下新建Count容器与Person容器

八、redux最终版

1.src/index.js

2.src/App.js

3.src/redux/store.js

4.src/redux/constant.js

5.src/redux/actions/count.js

6.src/redux/actions/person.js

7.src/redux/reducers/count.js

8.src/redux/reducers/person.js

9.src/redux/reducers/index.js

10.src/container/Count/index.jsx

11.src/container/Peson/index.jsx


一、redux简介

1.学习文档

  1. 英文文档: Redux - A predictable state container for JavaScript apps. | Redux
  2. 中文文档: 自述 · Redux

Github: GitHub - reduxjs/redux: Predictable state container for JavaScript apps

 2.redux是什么,什么时候使用

redux是专门用于做状态管理的JS库(不是react插件库)

某个组件的状态,需要让其他组件可以随时拿到(共享),总体原则:能不用就不用,如果不用比较吃力才考虑用

npm i redux

 

二、redux精简版(实现求和案例)

1.在src目录下新建一个redux文件夹:

(1) redux下在新建一个store.js

/* 
  该文件专门用于暴漏一个store对象,整个应用只有一个store对象
*/
// 引入legacy_createStore重命名为createStore
import { legacy_createStore } from 'redux'
// 引入为组件服务的reducer
import countReducer from './count_reducer'

export default legacy_createStore(countReducer)

(2)在redux下在心间一个count_reducer.js文件负责运算

/* 
    1.该文件是用于创建一个Count组件服务的reducer,reducer的本质就是一个函数   
    2.reducer函数会接收到两个参数,分别为:之前的状态(preState),动作对象(action)
    
*/
const initState = 0 //初始化状态

export default function countReducer(preState = initState, action) {
  if (preState === undefined) preState = 0
  // 从action对象中获取type、data
  const { type, data } = action
  // 根据type决定如何加工数据
  switch (type) {
    case 'increment': //如果是加
      return preState + data
    case 'decrement': // 如果是减
      return preState - data
    default:
      return preState;
  }
}

(3)Count组件的使用

引入store文件,import store from '../../redux/store'

   (1)store.getState()    获取初始值

   (2)store.dispatch({ type: "increment", data: value * 1 })   一个对象参数type表示action的行为,data为参数

   (3)需要在componentDidMount()生命周期里面检测redux的变化store.subscribe(()=>{this.setState({})})

import React, { Component } from 'react'
// 引入store用于获取redux中的状态
import store from '../../redux/store'

export default class Count extends Component {

  state = {
    count: 0
  }

  componentDidMount() {
    // 检测redux中状态的变化,只要变化,就调用render
    store.subscribe(() => {
      this.setState({})
    })
  }

  //加法
  increment = () => {
    const { value } = this.selectNumber
    store.dispatch({ type: "increment", data: value * 1 })
  }

  // 减法
  decrement = () => {
    const { value } = this.selectNumber
    store.dispatch({ type: "decrement", data: value * 1 })
  }

  // 奇数再加
  incrementIFOdd = () => {
    const { value } = this.selectNumber
    if (store.getState() % 2 !== 0) store.dispatch({ type: "increment", data: value * 1 })
  }

  // 异步加
  incrementAsync = () => {
    const { value } = this.selectNumber
    setTimeout(() => {
      store.dispatch({ type: "increment", data: value * 1 })
    }, 500);
  }

  render() {
    const { count } = this.state
    return (
      <div>
        <h1>当前求和为:{store.getState()}</h1>&nbsp;&nbsp;
        <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>
    )
  }
}

三、redux完整版(实现求和案例)

1.在src目录下新建一个redux文件夹:

(1) redux下在新建一个store.js

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

// 引入legacy_createStore重命名为createStore
import { legacy_createStore as createStore } from 'redux'
// 引入为组件服务的reducer
import countReducer from './count_reducer'

export default createStore(countReducer)

 (2)redux下新建一个count_action.js文件

/* 
  该文件专门为Count组件生成action对象
*/

import { INCREMENT, DECREMENT } from './constant'

export const createIncrementAction = data => ({ type: INCREMENT, data })

export const createDecrementAction = data => ({ type: DECREMENT, data })

(3)在redux下在心间一个count_reducer.js文件负责运算

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

const initState = 0 //初始化状态

export default function countReducer(preState = initState, action) {
  if (preState === undefined) preState = 0
  // 从action对象中获取type、data
  const { type, data } = action
  // 根据type决定如何加工数据
  switch (type) {
    case INCREMENT: //如果是加
      return preState + data
    case DECREMENT: // 如果是减
      return preState - data
    default:
      return preState;
  }
}

(4)新建一个constant.js文件,定义action使用的type避免写错

/* 
  该模块使用预定义action对象中type类型的常量值
*/

export const INCREMENT = "increment"
export const DECREMENT = "decrement"

2.使用Count.vue:

import React, { Component } from 'react'
// 引入store用于获取redux中的状态
import store from '../../redux/store'
// 引入actionCreator。专门用于创建action对象
import { createIncrementAction, createDecrementAction } from '../../redux/count_action'
export default class Count extends Component {

  state = {
    count: 0
  }

  componentDidMount() {
    // 检测redux中状态的变化,只要变化,就调用render
    store.subscribe(() => {
      this.setState({})
    })
  }

  //加法
  increment = () => {
    const { value } = this.selectNumber
    store.dispatch(createIncrementAction(value * 1))
  }

  // 减法
  decrement = () => {
    const { value } = this.selectNumber
    store.dispatch(createDecrementAction(value * 1))
  }

  // 奇数再加
  incrementIFOdd = () => {
    const { value } = this.selectNumber
    if (store.getState() % 2 !== 0) store.dispatch(createIncrementAction(value * 1))
  }

  // 异步加
  incrementAsync = () => {
    const { value } = this.selectNumber
    setTimeout(() => {
      store.dispatch(createIncrementAction(value * 1))
    }, 500);
  }

  render() {
    const { count } = this.state
    return (
      <div>
        <h1>当前求和为:{store.getState()}</h1>&nbsp;&nbsp;
        <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>
    )
  }
}

四、异步action版本(不一定需要使用)

1.同步与异步的区别:

action:是Object就是同步;   是function就是异步

实现异步action需要使用thunk     npm i  redux-thunk  ,并在store中配置

1.在src目录下新建一个redux文件夹:

(1) redux下在新建一个store.js

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

// 引入legacy_createStore重命名为createStore
import { legacy_createStore as createStore, applyMiddleware } from 'redux'
// 引入为组件服务的reducer
import countReducer from './count_reducer'
// 引入redux-thuk,用于支持异步action
import thunk from 'redux-thunk'
export default createStore(countReducer, applyMiddleware(thunk))

(2)constant.js

/* 
  该模块使用预定义action对象中type类型的常量值
*/

export const INCREMENT = "increment"
export const DECREMENT = "decrement"

(3)count_action.js

/* 
  该文件专门为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的值为函数
export const createIncrementAsyncAction = (data, time) => {
  return (dispatch) => {
    setTimeout(() => {
      dispatch(createIncrementAction(data))
    }, time)
  }
}

(4)count_reducer.js

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

const initState = 0 //初始化状态

export default function countReducer(preState = initState, action) {
  if (preState === undefined) preState = 0
  // 从action对象中获取type、data
  const { type, data } = action
  // 根据type决定如何加工数据
  switch (type) {
    case INCREMENT: //如果是加
      return preState + data
    case DECREMENT: // 如果是减
      return preState - data
    default:
      return preState;
  }
}

2.Count.vue使用

  // 异步加
  incrementAsync = () => {
    const { value } = this.selectNumber
    // setTimeout(() => {
    store.dispatch(createIncrementAsyncAction(value * 1, 500))
    // }, 500);
  }

五、react-redux官方推荐

npm i react-redux              安装官方的

 1.新建一个container文件夹在下面在新建一个Count的组件作为CountUI组件的容器组件

//引入Count的UI组件
import CountUI from '../../components/Count'

// 引入connect用于连接UI组件与redux
import { connect } from 'react-redux'

import {
  createDecrementAction,
  createIncrementAction,
  createIncrementAsyncAction,
} from '../../../src/redux/count_action'

// a函数返回的对象的
// key就作为转递给props的key,value就作为传递给的props的value值作为状态传递给了UI组件--状态
function mapStateToProps(state) {
  return { count: state }
}

// mapDispatchToProps函数的返回的是一个对象
// a函数返回的对象的
// key就作为转递给props的key,value就作为传递给的props的value值作为状态传递给了UI组件--操作方法
function mapDispatchToProps(dispatch) {
  return {
    // 通知reduce执行加法
    jia: (number) => dispatch(createIncrementAction(number)),
    jian: (number) => dispatch(createDecrementAction(number)),
    jiaAsync: (number, time) =>
      dispatch(createIncrementAsyncAction(number, time)),
  }
}

// 使用connect()()创建并暴漏一个Count的容器组件
export default connect(mapStateToProps, mapDispatchToProps)(CountUI)

2.在App.jsx里面导入的Count容器组件,并传入store

import Count from './containers/Count';
import store from './redux/store';

function App() {
  return (
    <div>
      {/* 给容器组件传递store */}
      <Count store={store} />
    </div>
  );
}

3.component/Count/index.jsx使用

import React, { Component } from 'react'

export default class Count extends Component {

  state = {
    count: 0
  }

  //加法
  increment = () => {
    const { value } = this.selectNumber
    this.props.jia(value - 0)
  }

  // 减法
  decrement = () => {
    const { value } = this.selectNumber
    this.props.jian(value - 0)
  }

  // 奇数再加
  incrementIFOdd = () => {
    const { value } = this.selectNumber
    if (this.props.count % 2 !== 0) this.props.jia(value - 0)
  }

  // 异步加
  incrementAsync = () => {
    const { value } = this.selectNumber
    this.props.jiaAsync(value - 0, 1000)
  }

  render() {
    return (
      <div>
        <h1>当前求和为:{this.props.count}</h1>&nbsp;&nbsp;
        <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>
    )
  }
}

4.redux文件与上面的是一样的

六、react-redux的优化

优化的内容:(1)简写了connect,(2)全局配置store (3)简写UI组件与容器组件

1.根目录的index.js文件:利用provide向全局提供store

import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

2.App.js文件不需要传递store

import Count from './containers/Count';

function App() {
  return (
    <div>
      <Count />
    </div>
  );
}

3.container/Count/index.js下面的写法

import { connect } from 'react-redux'
import {
  createDecrementAction,
  createIncrementAction,
  createIncrementAsyncAction
} from "../../../src/redux/count_action";
import React, { Component } from 'react'

class Count extends Component {

  state = {
    count: 0
  }

  //加法
  increment = () => {
    const { value } = this.selectNumber
    this.props.jia(value - 0)
  }

  // 减法
  decrement = () => {
    const { value } = this.selectNumber
    this.props.jian(value - 0)
  }

  // 奇数再加
  incrementIFOdd = () => {
    const { value } = this.selectNumber
    if (this.props.count % 2 !== 0) this.props.jia(value - 0)
  }

  // 异步加
  incrementAsync = () => {
    const { value } = this.selectNumber
    this.props.jiaAsync(value - 0, 1000)
  }

  render() {
    return (
      <div>
        <h1>当前求和为:{this.props.count}</h1>&nbsp;&nbsp;
        <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>
    )
  }
}

export default connect(
  state => ({ count: state }),

  // mapDispatchToprops 的一般写法
  /* dispatch => ({
    jia: number => dispatch(createIncrementAction(number)),
    jian: number => dispatch(createDecrementAction(number)),
    jiaAsync: (number, time) => dispatch(createIncrementAsyncAction(number, time)),
  }) */

  // mapDispatchToprops 的一般写法 dispatch会自动分发不用调dispatch
  {
    jia: createIncrementAction,
    jian: createDecrementAction,
    jiaAsync: createIncrementAsyncAction
  }

)(Count)

4.redux其他代码没变

七、react-redux的数据共享(正式开发)

1.redux文件夹里面分别新建reducers文件夹与actions文件夹和store.js和constant.js文件夹

(1)redux/reducers/count.js

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

const initState = 0 //初始化状态

export default function countReducer(preState = initState, action) {
  if (preState === undefined) preState = 0
  // 从action对象中获取type、data
  const { type, data } = action
  // 根据type决定如何加工数据
  switch (type) {
    case INCREMENT: //如果是加
      return preState + data
    case DECREMENT: // 如果是减
      return preState - data
    default:
      return preState;
  }
}

(2)redux/reducers/person.js

import { ADD_PERSON } from "../constant";

const initState = [{ id: 1, 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
  }
}

(3)redux/actions/count.js

/* 
  该文件专门为Count组件生成action对象
*/

import store from '../store'
import { INCREMENT, DECREMENT } from '../constant'

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

export const createDecrementAction = data => ({ type: DECREMENT, data })

// 异步action,就是值action的值为函数
export const createIncrementAsyncAction = (data, time) => {
  return (dispatch) => {
    setTimeout(() => {
      dispatch(createIncrementAction(data))
    }, time)
  }
}

(4)redux/actions/person.js

import { ADD_PERSON } from "../constant";

// 创建增加一个人的person
export const createAddPersonAction = personObj => ({ type: ADD_PERSON, data: personObj })

(5)redux/store.js

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

// 引入legacy_createStore重命名为createStore
import { legacy_createStore as createStore, applyMiddleware, combineReducers } from 'redux'
// 引入为Count组件服务的reducer
import countReducer from './reducer/count'
// 引入为Person组件服务的reducer
import personReducer from './reducer/person'
// 引入redux-thuk,用于支持异步action
import thunk from 'redux-thunk'

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

export default createStore(allReducer, applyMiddleware(thunk))

(6)redux/constant.js

/* 
  该模块使用预定义action对象中type类型的常量值
*/

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

2.使用:新建container文件下新建Count容器与Person容器

(1)src/container/Count/index.jsx

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { createDecrementAction, createIncrementAction, createIncrementAsyncAction } from '../../redux/actions/count'

class Count extends Component {

  state = {
    count: 0
  }

  //加法
  increment = () => {
    const { value } = this.selectNumber
    this.props.jia(value - 0)
  }

  // 减法
  decrement = () => {
    const { value } = this.selectNumber
    this.props.jian(value - 0)
  }

  // 奇数再加
  incrementIFOdd = () => {
    const { value } = this.selectNumber
    if (this.props.count % 2 !== 0) this.props.jia(value - 0)
  }

  // 异步加
  incrementAsync = () => {
    const { value } = this.selectNumber
    this.props.jiaAsync(value - 0, 1000)
  }

  render() {
    return (
      <div>
        <h1>我是Count组件</h1>
        <h4>当前求和为:{this.props.count},下方组件人数为{this.props.renshu}</h4>&nbsp;&nbsp;
        <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>
    )
  }
}

export default connect(
  state => ({
    renshu: state.rens.length,
    count: state.he
  }),

  // mapDispatchToprops 的一般写法
  /* dispatch => ({
    jia: number => dispatch(createIncrementAction(number)),
    jian: number => dispatch(createDecrementAction(number)),
    jiaAsync: (number, time) => dispatch(createIncrementAsyncAction(number, time)),
  }) */

  // mapDispatchToprops 的一般写法 dispatch会自动分发不用调dispatch
  {
    jia: createIncrementAction,
    jian: createDecrementAction,
    jiaAsync: createIncrementAsyncAction
  }

)(Count)

(2)src/container/Person/index.jsx

import React, { Component } from 'react'
import { nanoid } from 'nanoid'
import { connect } from 'react-redux'
import { createAddPersonAction } from '../../redux/actions/person'

class Person extends Component {
  addPereson = () => {
    // 获取用户的输入
    const name = this.nameNode.value
    const age = this.ageNode.value
    const personObj = { id: nanoid(), name, age }
    this.props.jiaYiren(personObj)
    this.nameNode.value = ""
    this.ageNode.value = ""
  }

  render() {
    return (
      <div>
        <h1>我是Person组件,上方组件的和为{this.props.he}</h1>
        <input ref={c => this.nameNode = c} type="text" placeholder='姓名' />
        <input ref={c => this.ageNode = c} type="text" placeholder='年龄' />
        <button onClick={this.addPereson}>添加一个人</button>
        <hr />
        <ul>
          {
            this.props.yiduiren.map((item) => {
              return (<li key={item.id}>名字{item.name}-----------------------年龄{item.age}</li>)
            })
          }
        </ul>
        <hr />
      </div>
    )
  }
}

export default connect(
  state => ({ yiduiren: state.rens, he: state.he }), //映射状态
  {
    jiaYiren: createAddPersonAction
  }
)(Person)

八、redux最终版

1.src/index.js

import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>   //provide向外提供store
    <App />
  </Provider>
);

2.src/App.js

function App() {
  return (
    <div>
      {/* 给容器组件传递store */}
      <Count />
      <hr />
      <Person />
    </div>
  );
}

3.src/redux/store.js

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

// 引入legacy_createStore重命名为createStore
import { legacy_createStore as createStore, applyMiddleware, combineReducers } from 'redux'
// 引入汇总后的reducer
import allReducer from './reducer'
// 引入redux-thuk,用于支持异步action
import thunk from 'redux-thunk'
// 引入redux-devtools-extension
import { composeWithDevTools } from 'redux-devtools-extension'

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

4.src/redux/constant.js

/* 
  该模块使用预定义action对象中type类型的常量值
*/

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

5.src/redux/actions/count.js

/* 
  该文件专门为Count组件生成action对象
*/

import store from '../store'
import { INCREMENT, DECREMENT } from '../constant'

// 同步action,就是值action的值为Object类型的对象
export const increment = data => ({ type: INCREMENT, data })

export const decrement = data => ({ type: DECREMENT, data })

// 异步action,就是值action的值为函数
export const incrementAsync = (data, time) => {
  return (dispatch) => {
    setTimeout(() => {
      dispatch(increment(data))
    }, time)
  }
}

6.src/redux/actions/person.js

import { ADD_PERSON } from "../constant";

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

7.src/redux/reducers/count.js

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

const initState = 0 //初始化状态

export default function countReducer(preState = initState, action) {
  if (preState === undefined) preState = 0
  // 从action对象中获取type、data
  const { type, data } = action
  // 根据type决定如何加工数据
  switch (type) {
    case INCREMENT: //如果是加
      return preState + data
    case DECREMENT: // 如果是减
      return preState - data
    default:
      return preState;
  }
}

8.src/redux/reducers/person.js

import { ADD_PERSON } from "../constant";

const initState = [{ id: 1, 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
  }
}

9.src/redux/reducers/index.js

/* 
  该文件用于汇总所有的reducer为一个总的reducer
*/

// 引入combineReducers,用于汇总多个reducer
import { combineReducers } from 'redux'

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

export default combineReducers({
  count,
  persons
})

10.src/container/Count/index.jsx

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { increment, decrement, incrementAsync } from '../../redux/actions/count'

class Count extends Component {

  state = {
    count: 0
  }

  //加法
  increment = () => {
    const { value } = this.selectNumber
    this.props.increment(value - 0)
  }

  // 减法
  decrement = () => {
    const { value } = this.selectNumber
    this.props.decrement(value - 0)
  }

  // 奇数再加
  incrementIFOdd = () => {
    const { value } = this.selectNumber
    if (this.props.count % 2 !== 0) this.props.increment(value - 0)
  }

  // 异步加
  incrementAsync = () => {
    const { value } = this.selectNumber
    this.props.incrementAsync(value - 0, 1000)
  }

  render() {
    return (
      <div>
        <h1>我是Count组件</h1>
        <h4>当前求和为:{this.props.count},下方组件人数为{this.props.persons}</h4>&nbsp;&nbsp;
        <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>
    )
  }
}

export default connect(
  state => ({
    persons: state.persons.length,
    count: state.count
  }),

  // mapDispatchToprops 的一般写法
  /* dispatch => ({
    jia: number => dispatch(createIncrementAction(number)),
    jian: number => dispatch(createDecrementAction(number)),
    jiaAsync: (number, time) => dispatch(createIncrementAsyncAction(number, time)),
  }) */

  // mapDispatchToprops 的一般写法 dispatch会自动分发不用调dispatch
  {
    increment,
    decrement,
    incrementAsync
  }

)(Count)

11.src/container/Peson/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>
        <h1>我是Person组件,上方组件的和为{this.props.count}</h1>
        <input ref={c => this.nameNode = c} type="text" placeholder='姓名' />
        <input ref={c => this.ageNode = c} type="text" placeholder='年龄' />
        <button onClick={this.addPerson}>添加一个人</button>
        <hr />
        <ul>
          {
            this.props.persons.map((item) => {
              return (<li key={item.id}>名字{item.name}-----------------------年龄{item.age}</li>)
            })
          }
        </ul>
        <hr />
      </div>
    )
  }
}

export default connect(
  state => ({ persons: state.persons, count: state.count }), //映射状态
  {
    addPerson
  }
)(Person)

完成这个功能就代表懂了 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redux 是一个用于管理应用程序状态的 JavaScript 库。它的实现原理可以简单概括为以下几个关键概念和步骤: 1. **单一数据源:** Redux 应用的状态被存储在一个单一的 JavaScript 对象中,称为 "store"。这个状态对象存储了整个应用程序的状态树。 2. **纯函数修改状态:** Redux 中的状态是只读的,唯一改变状态的方式是通过 dispatch 一个 action。Action 是一个描述状态变化的普通 JavaScript 对象,其中包含一个 `type` 字段来表示操作类型,以及可选的负载数据。Reducer 是纯函数,接收旧的状态和 action,返回一个新的状态。它描述了如何根据 action 来更新应用程序的状态树。 3. **状态订阅和通知:** Redux 提供了 `subscribe` 方法,用于订阅 store 的变化。当状态发生变化时,订阅者会被通知,并可以执行相应的操作。 4. **中间件增强:** Redux 支持中间件机制,通过中间件可以拦截和处理 action,以实现一些额外的功能。例如,中间件可以用于异步操作、日志记录、错误处理等。 5. **连接 React 组件:** Redux 可以与 React 无缝集成。通过 `react-redux` 库提供的 `Provider` 和 `connect` 方法,可以将 Redux 的 store 注入到 React 组件中,并根据需要连接组件与状态。 总的来说,Redux 的实现原理是通过单一数据源、纯函数修改状态、订阅通知和中间件增强来管理应用程序的状态,并与 React 紧密集成,实现了可预测、可维护的状态管理。这种架构模式使得应用程序的状态变化可追踪、可调试,并且易于扩展和测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值