React进阶笔记【3_组件间的数据传递】

2022/4/5 ReactJS

# 单向数据流

当前组件的 state 以 props 的 形式流动时,只能流向组件树中比自己层级更低的组件。

# 父子通信

React 的数据流是单向的,父组件可以直接将 this.props 传入子组件,实现父子通信。

# 子父通信

父组件传递给子组件的是一个绑定了自身上下文的函数,那么子组件在调用该函数时,就可以将数据以函数入参的形式给出去。

# 兄弟通信

  1. 可以通过子到父,父到兄弟的方式来实现通信(层层props)。
  2. 发布订阅模式。

# Context API

Context API 是 React 官方提供的一种组件树全局通信的方式。在 React 16.3 之前,Context API 由于存在各种局限性, 并不被 React 官方提倡使用,开发者更多的是把它作为一个概念来探讨。而从 v16.3.0 开始,React 对 Context API 进行了改进,新的 Context API 具备更强的可用性。

# React.createContext

const AppContext = React.createContext(defaultValue)
const { Provider, Consumer } = AppContext
1
2

# Provider

<Provider value={title: this.state.title}>
</Provider>
// value 表示向后传递的数据,可以被 Consumer 消费
1
2
3

# Consumer

<Consumer>
  { value => <div>{value.title}</div> }
</Consumer>
// 获取 Provider 的数据,返回一个函数
// 如果 Provider 没有数据,则会获取 React.createContext 中的 defaultValue
1
2
3
4
5

# 旧的 Context API 的问题

  1. 代码不够优雅,很难迅速辨认出谁是 Provider,谁是 Consumer
  2. 无法保证数据在生产者和消费者之家的及时同步

如果组件提供的一个 Context 发生了变化,而中间父组件的 shouldComponentUpdate 返回 false,那么使用到该值的后代组件不会进行更新。使用了 Context 的组件则完全失控,所以基本上没有办法能够可靠的更新 Context。

—— React 官方

# 新的 Context API 的改进

即便组件的 shouldComponentUpdate 返回 false,它仍然可以 “穿透” 组件,继续向后代组件进行传播,进而确保了数据生产者和数据消费者之间数据的一致性。

# Redux 简介

对于简单的跨层级组件通信,可以使用 发布订阅模式 或者 Context API 来实现数据的传输,如果需要维护的状态很多,组件关系很复杂的时候,就可以使用 Redux 来实现。

Redux 是 JavaScript 状态容器,它提供可预测的状态管理。

—— React 官方

Redux 包括三部分:store、action、reducer,其中:

  • store 是单一数据源,且只读
  • action 是对变化的描述
  • reducer 负责对变化进行分发和处理,结果会返回给 store
视图层的所有数据都来自 store,如果要修改数据,只有一种途径:派发 action,action 会被 reducer 读取,进而通过 action 的不同,对数据进行修改,生成新的 state。新的 state 会更新到 store 对象里, 进而视图层面做出对应的改变。

⚠️ 在 Redux 的工作流程中,数据流是严格单向的。

import { createStore } from 'redux'

// 创建 reducer,注意:reducer 是一个纯函数
const reducer = (state, action) => {
  // 此处执行 state 逻辑,最后会返回一个 state
  return new_state
}

// 基于 reducer 创建 state
const store = createStore(reducer)

// 创建 aciton,该 action 用 type 为 ADD 来标识
const action = {
  type: "ADD",
  payload: "<p>aaa</p>"
}

// 使用 dispatch 来派发 action,action 会进入到 reducer 中触发对应的更新
store.dispatch(action)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19