Redux 数据流和 React 组件生命周期

2025-06-10

Redux 数据流和 React 组件生命周期

几乎所有想学习 Redux 的人都见过这张图片。现在对我来说,它非常直观,但在我刚开始学习 Redux 时,它很难理解。为了更好地理解 Redux 中的数据流,在本文中,我将尝试解释 Redux 如何与 React 协同工作。并尝试通过 React Hooks 实现 Redux。

redux-flow

首先,让我们从 Redux 开始。

Redux 是一个状态管理系统。因此,我们需要:

  1. 拯救国家的地方
  2. 获取状态的方法
  3. 改变状态的方法

这就是我们在使用 Redux 时所做的事情:
1.store是我们保存状态的地方



import { createStore } from "redux";
import { reducer } from "./reduxModule";

const store = createStore(reducer);


Enter fullscreen mode Exit fullscreen mode

2.getState是获取状态的方法



const state = store.getState();


Enter fullscreen mode Exit fullscreen mode

3. action&reducer是改变 mapStateToProps 的方法



const INCREMENT = "redux/increment";
const initialState = {
  counter: 0,
};

export const reducer = (state = initialState, action) => {
  switch (action.type) {
    case INCREMENT:
      return {
        counter: state.counter + action.amount
      };
    default:
      return state;
  }
};

export const incrementAction = (amount = 1) => {
  return {
    type: INCREMENT,
    amount,
  };
};


Enter fullscreen mode Exit fullscreen mode

我们需要进一步解释的部分是actionreducer。Redux通过
更新状态告诉它想要做什么。然后根据 提供的类型和附加数据更新状态actionreduceractionreducerreduceraction

为什么要使用actionreducer

我曾与很多人讨论过为什么他们在项目中使用 Redux。几乎每次答案都是 - “易于在组件之间共享 props 并防止prop-drilling ”。我想这是因为回到我们还没有稳定的时代context API,使用 Redux 共享 props 似乎是一个合理的选择。但在我看来,这不是 Redux 的核心概念。
使用actionreducer更新状态可以使其更容易控制。状态只能根据我们定义的操作进行更改。关于如何更改状态的所有逻辑都在中reducer。这可以使它更容易维护。
这个想法就像finite-state machine。如果我们想要添加更多状态,
只需声明另一个动作并将逻辑添加到 reducer 中。
如果你有兴趣了解更多关于state machines。你可以查看Kent C. Dodds 写的这篇文章。

现在,我们可以像这样将 Redux 形象化。

  1. 在初始阶段,reducer 接收并返回初始状态。因此,我们将在 getState 中获取初始状态 ({counter: 0})。redux-init
  2. dispatch在更新阶段,我们向 reducer发送一个增量动作(在 redux 中,我们称之为),通过我们在 reducer 中定义的 switch 语句,它将返回一个新的状态({counter: 0})。redux-更新

接下来我们在 React 中应用

当我们想要在 React 中实现 Redux 时,我们还需要三样东西:

  1. 在 React 中保存存储状态
  2. 获取 React 组件中的状态
  3. React 组件中的 dispatch 动作

对于项目 1,react-redux有一个名为 的组件Provider可以帮助我们做到这一点。



import { createStore } from "redux";
import { Provider } from "react-redux";

const store = createStore(reducer);

return (
  <Provider store={store}>
    <Container />
  </Provider>
)


Enter fullscreen mode Exit fullscreen mode

对于第 2 项和第 3 项,react-redux提供另一个 HOC 调用connect。它会将 state 和 action 转换为组件 props。这样我们就可以在 React 组件中使用它了。



import { connect } from "react-redux";
import { incrementAction } from "./reduxModule";

const mapStateToProps = state => ({ counter: state.counter });
const mapDispatchToProps = { incrementAction };
export default connect(mapStateToProps, mapDispatchToProps)(Comp);


Enter fullscreen mode Exit fullscreen mode

现在,我们的组件已经能够接收状态并执行 action 了。因此,像这样完成我们的组件就很容易了。



import React from "react";

export default function Comp({ counter, incrementAction }) {
  function handleIncreaseOne() {
    incrementAction(1);
  }
  function handleIncreaseTen() {
    incrementAction(10);
  }
  return (
    <div>
      <span>{counter}</span>
      <div>
        <button onClick={handleIncreaseOne}>+1</button>
        <button onClick={handleIncreaseTen}>+10</button>
      </div>
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

以下是供您参考的全部代码:https://github.com/oahehc/react-redux-example/tree/basic

将 Redux 集成到 React 后,可视化效果应该是这样的。

react-redux-init
React-redux-更新

通过 React Hooks 实现 Redux

现在我们知道了 Redux 如何帮助我们管理状态,所以我们可以尝试通过 React hooks 应用同样的想法。
(* 这只是一个例子,用来演示 Redux 的基本思想,请不要用它来替换ReduxReact-Redux的项目。如果你想了解更多关于 Redux 的细节,你可以查看Dan Abramov 创建的这个教程

) 就像我们之前做的那样,我们可以将其拆分成三个项目。

  1. 保存状态的地方 ->context API
  2. 在 React 组件中获取状态的方法 ->useContext
  3. 在 React 组件中改变状态的方法 -> useContext&useReducer


// @ReduxModule.js : reducer and action
const INCREMENT = "redux/increment";

export function reducer(state, action) {
  switch (action.type) {
    case INCREMENT:
      return state + action.amount;
    default:
      return state;
  }
}

export function incrementActionCreator(dispatch) {
  return amount => {
    dispatch({
      type: INCREMENT,
      amount
    });
  };
}


Enter fullscreen mode Exit fullscreen mode


// @Provider.js : apply context API to save the state
import React, { useReducer } from "react";
import { reducer, incrementActionCreator } from "./ReduxModule";

export const ReduxContext = React.createContext();
const initialState = 0;
function ReduxProvider({ children }) {
  const [counter, dispatch] = useReducer(reducer, initialState);

  return (
    <ReduxContext.Provider
      value={{ counter, incrementAction: incrementActionCreator(dispatch) }}
    >
      {children}
    </ReduxContext.Provider>
  );
}

export default ReduxProvider;


Enter fullscreen mode Exit fullscreen mode


// @Comp.js : apply useContext to get state and action from Context
import React, { useContext } from "react";
import { ReduxContext } from "./Provider";

export default function Comp() {
  const { counter, incrementAction } = useContext(ReduxContext);

  function handleIncreaseOne() {
    incrementAction(1);
  }
  function handleIncreaseTen() {
    incrementAction(10);
  }
  return (
    <div>
      <span>{counter}</span>
      <div>
        <button onClick={handleIncreaseOne}>+1</button>
        <button onClick={handleIncreaseTen}>+10</button>
      </div>
    </div>
  );
}



Enter fullscreen mode Exit fullscreen mode

参考:https ://github.com/oahehc/react-redux-example/tree/custom-redux

当我们通过 React hooks 实现 Redux 时,我们使用useContextuseReducer。这将引出 Redux 的核心概念:

  1. useContext :与多个组件共享状态
  2. useReducer :通过状态机处理状态

结论

感谢您的阅读。希望本文能让 Redux 更容易理解。如果您有任何问题或反馈,请随时留下您的评论。

--

参考

鏂囩珷鏉ユ簮锛�https://dev.to/oahehc/redux-data-flow-and-react-component-life-cycle-11n
PREV
今天的 JavaScript React Dev 面试题
NEXT
如何使用纯 CSS 在您的网站上启用暗模式?