react-redux 基本原理 & 使用redux 处理异步逻

2023-01-02  本文已影响0人  廖雪青

Redux 出现的背景

随着对 React 使用的深入,你会发现组件级别的 state,和从上而下传递的 props 这两个状态机制,无法满足复杂功能的需要,例如跨层级之间的组件的数据共享和传递,Redux应运而生。

state应用 & redux应用对比
左图是单个 React 组件,它的状态可以用内部的 state 来维护,而且这个 state 在组件外部是无法访问的。
右图则是使用 Redux 的场景,用全局唯一的 Store 维护了整个应用程序的状态。对于页面的多个组件,都是从这个 Store 中获取状态的,从而保证组件之间能够共享状态。

从这张对比图,我们可以看到 Redux Store 的两个特点:

有两个场景可以典型地体现出这些特点:

Redux的三个基本概念

Redux 主要引入了以下三个概念:

state & action & reducer之间的关系
所有对于Store的修改都必须通过Reducer去完成,这样一方面能保证数据的不可变性(Immutable),同时也带来了可预测性和易于调试的特点 。

如何在React中使用Redux: react-redux

在实际场景中,Redux Store 中的状态最终一定是会体现在 UI 上的,即通过 React 组件展示给用户。那么如何建立 Redux 和 React 的联系呢?

Facebook 提供的 react-redux 工具库,作用就是建立一个桥梁,让 React 和 Redux 实现互通。

import React from 'react'
import ReactDOM from 'react-dom'

import { Provider } from 'react-redux'
import store from './store'

import App from './App'

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

Provider 组件作为整个应用程序的根节点,并将 Store 作为属性传给了这个组件,这样所有下层的组件就都能够使用 Redux 了。

在函数组件中使用 Redux 就非常简单了:
利用 react-redux 提供的 useSelectoruseDispatch 这两个 Hooks。

import React from 'react'
import { useSelector, useDispatch } from 'react-redux'

export function Counter() {
  // 从 state 中获取当前的计数值
  const count = useSelector(state => state.value)

  // 获得当前 store 的 dispatch 方法
  const dispatch = useDispatch()

  // 在按钮的 click 时间中去分发 action 来修改 store
  return (
    <div>
      <button
        onClick={() => dispatch({ type: 'counter/incremented' })}
      >+</button>
      <span>{count}</span>
      <button
        onClick={() => dispatch({ type: 'counter/decremented' })}
      >-</button>
    </div>
  )
}
react-redux的单向数据流

使用Redux处理异步逻辑

处理异步逻辑也常常被称为异步 Action,它几乎是 React 面试中必问的一道题,可以认为这是 Redux 使用的进阶场景。

只有能够解释清楚异步 Action,才算是真正理解了 Redux

例:异步场景-发送请求获取数据

不推荐:在函数组件中发送请求 - Store 完全作为一个存放数据的地方

function DataList() {
const dispatch = useDispatch();
// 在组件初次加载时发起请求
useEffect(() => {
  // 请求发送时
  dispatch({ type: 'FETCH_DATA_BEGIN' });
  fetch('/some-url').then(res => {
    // 请求成功时
    dispatch({ type: 'FETCH_DATA_SUCCESS', data: res });
  }).catch(err => {
    // 请求失败时
    dispatch({ type: 'FETCH_DATA_FAILURE', error: err });
  })
}, []);

// 绑定到 state 的变化
const data = useSelector(state => state.data);
const pending = useSelector(state => state.pending);
const error = useSelector(state => state.error);

// 根据 state 显示不同的状态
if (error) return 'Error.';
if (pending) return 'Loading...';
return <Table data={data} />;
}

很显然,发送请求获取数据并进行错误处理这个逻辑是不可重用的。假设我们希望在另外一个组件中也能发送同样的请求,就不得不将这段代码重新实现一遍。因此,Redux 中提供了 middleware 这样一个机制,让我们可以巧妙地实现所谓异步 Action 的概念。

推荐:使用 middlewate - dispatch 一个函数用于发送请求

这一套结合 redux-thunk 中间件的机制,我们就称之为异步 Action。

所以说异步 Action 并不是一个具体的概念,而可以把它看作是 Redux 的一个使用模式。它通过组合使用同步 Action ,在没有引入新概念的同时,用一致的方式提供了处理异步逻辑的方案。

上一篇 下一篇

猜你喜欢

热点阅读