[React] 11 - Redux: review

Ref: Redux中文文档

Ref: React 讀書會 - B團 - Level 19 Redux 深入淺出

Ref: React+Redux 分享會

Ruan Yifeng, Redux 架构: 教程一有代码)、教程二教程三

 

Redux 入门教程 #1 课程介绍

Redux 入门教程 #2 为什么需要 Redux

Redux 入门教程 #3 什么是 Redux

Redux 入门教程 #4 创建页面

Redux 入门教程 #5 单独使用 Redux

Redux 入门教程 #6 使用 react-redux

 

 

 

课前阅读


背景知识

(1) 首先,复习 Flux[React] 07 - Flux: react communicates with mongodb

  • 原始方案中,pages目录下其实也是组件的效果;
  • 右边的flux pattern到底带来了什么?

详见Flux章节和链接。

 

(2) 之后,让我们开始对 Redux 认真学习。

2015年,Redux 出现,将 Flux 与函数式编程结合一起,很短时间内就成为了最热门的前端架构。

 

* 解决什么问题?

A如何把参数传给B?react的单向流不好处理。

或者,使用嵌入式写法,比如A触发事件,B监听事件。

但嵌入式写法不推荐。

 

  • React两大不利之处,
  • 代码结构
  • 组件之间的通信
  • 从需求角度看,
  • 用户的使用方式复杂
  • 不同身份的用户有不同的使用方式(比如普通用户管理员
  • 多个用户之间可以协作
  • 与服务器大量交互,或者使用了WebSocket
  • View要从多个来源获取数据
  • 从组件角度看,
  • 某个组件的状态,需要共享
  • 某个状态需要在任何地方都可以拿到
  • 一个组件需要改变全局状态
  • 一个组件需要改变另一个组件的状态

 

 

应用程序状态管理组件

可见,解决组件间的通信便捷性问题。

 

  • 安装包

$ mkdir reduxtest
$ cd reduxtest
$ npm init -y
# 安装 Redux
$ npm install redux
# 安装 Redux Toolkit, 自带 Redux Core
# $ npm install @reduxjs/toolkit

 

  • 使用 "Redux模版" 建立工程

# Redux + Toolkit + 样例代码 = 最佳实践
$ npx create-react-app my-redux-app --template redux
# Redux + Toolkit + 样例代码 + Typescript = 最佳实践
$ npx create-react-app my-redux-app --template redux-typescript

一个例子,体现了集中式的 store 的状态管理。

const redux = require('redux');

/**
 * 初期状态数据
 */
const initState = {
    viewCount: 0,
}

/**
 * Reducer函数
 *   负责状态数据的更新
 * 
 * @param {*} state  当前状态数据 (旧状态)
 * @param {*} action 处理区分/处理类别
 * 
 * @returns 新的状态数据
 */
const reduxReducer = (state = initState, action) => {
    console.log("DEBUG")
    console.log("DEBUG", "旧状态->", state, "Reducer动作->", action)
let resultState = {} switch (action.type) { case 'add': resultState.viewCount = state.viewCount + 1 break case 'minus': resultState.viewCount = state.viewCount - 1 break case 'multiply': resultState.viewCount = state.viewCount * 10 break default: resultState.viewCount = state.viewCount break } console.log("DEBUG", "新状态->", resultState) return resultState } /** * 应用程序状态,一般情况下,将 export default store */ const store = redux.createStore(reduxReducer);
/** * 通过 ”订阅状态“ 跟踪 ”数据的变化“,用来完成更新UI等操作 */ store.subscribe(() => { console.log("INFO ", "所有订阅者侦听到了状态改变->", store.getState())  // 得到 reduxReducer 返回值显示出来 }) /** * 调用状态更新处理 */ // 父组件发出 // store.dispatch({ type: 'add' }) // dispatch 触发了 reduxReducer (就是那个统一管理的大的store),以 update this state.
// 子组件发出 // store.dispatch({ type: 'add' })
// 孙组件发出 // store.dispatch({ type: 'multiply' })
// 曾孙组件发出 // store.dispatch({ type: 'minus' })

 

React Redux

Ref: https://react-redux.js.org/

  • 安装
$ npm install redux react-redux
$ npm start

 

第一步,新建 ./store/index.js,这里只是构建并导出了store

const redux = require('redux');

/**
 * 初期状态数据
 */
const initState = {
    viewCount: 0,
}

/**
 * Reducer函数
 *   负责状态数据的更新
 * 
 * @param {*} state  当前状态数据
 * @param {*} action 处理区分/处理类别
 * 
 * @returns 新的状态数据
 */
const reduxReducer = (state = initState, action) => {
    console.log("DEBUG")
    console.log("DEBUG", "旧状态->", state, "Reducer动作->", action)
    let resultState = {}
    switch (action.type) {
        case 'add':
            resultState.viewCount = state.viewCount + 1
            break
        case 'minus':
            resultState.viewCount = state.viewCount - 1
            break
        case 'multiply':
            resultState.viewCount = state.viewCount * 10
            break
        default:
            resultState.viewCount = state.viewCount
            break
    }
    console.log("DEBUG", "新状态->", resultState)
    return resultState
}

/**
 * 应用程序状态
 */
const store = redux.createStore(reduxReducer);

/**
 * 输出状态对象
 */
export default store;
./src/store/index.js

 

第二步,以下引用 store,注意使用的方式。

// index.js

import { Provider } from 'react-redux'; import store from './store' ... <Provider store={store}> <App /> </Provider> ...

index.js 是整个工程的入口点。

 

第三步,创建一个 使用redux 的组件。

因为上图中“大环境”下有 Provier提供了store;所以这里的 useDispatch 知道与哪个store 相关联。

// ./components/LearnRedux.js

import React from "react"; import { useSelector, useDispatch } from "react-redux"; const LearnRedux = () => { const viewCount = useSelector(state => state.viewCount) // ----> 利用redux提供的 两个钩子函数 的通信过程。这里没有提及“容器组件”,所以使用了 useSelector() const dispatch= useDispatch() const btn_click = (type) => { dispatch({ type: type }) } return ( <React.Fragment> <h1>LearnRedux</h1> <h2>{viewCount}</h2> <hr /> <div> <button className="btn btn-primary btn-lg m-1" onClick={() => btn_click('add')}>Add</button> <button className="btn btn-success btn-lg m-1" onClick={() => btn_click('minus')}>Minus</button> <button className="btn btn-danger btn-lg m-1" onClick={() => btn_click('multiply')}>Multiply</button> </div> </React.Fragment> ) } export default LearnRedux;

 

第四步,将上一步的组件加入到程序中。

// ./App.js

import LearnRedux from "./components/LearnRedux"; ... <LearnRedux></LearnRedux> ....

 

点击按钮:btn_click --> dispatch --> 把这个消息分发给store,用以更新其中的 state。

通过钩子函数 useSelector,再返回 更新后的 state。

 

 

 

 

Redux Toolkit

Ref: https://redux-toolkit.js.org/

posted @ 2018-05-16 15:15  郝壹贰叁  阅读(232)  评论(0编辑  收藏  举报