javascript - 为什么 useReducer 的调度会导致重新渲染?

标签 javascript reactjs redux react-hooks use-reducer

假设我实现了一个简单的全局加载状态,如下所示:

// hooks/useLoading.js
import React, { createContext, useContext, useReducer } from 'react';

const Context = createContext();

const { Provider } = Context;

const initialState = {
  isLoading: false,
};

function reducer(state, action) {
  switch (action.type) {
    case 'SET_LOADING_ON': {
      return {
        ...state,
        isLoading: true,
      };
    }
    case 'SET_LOADING_OFF': {
      return {
        ...state,
        isLoading: false,
      };
    }
  }
}

export const actionCreators = {
  setLoadingOn: () => ({
    type: 'SET_LOADING_ON',
  }),
  setLoadingOff: () => ({
    type: 'SET_LOADING_OFF',
  }),
};

export const LoadingProvider = ({ children }) => {
  const [{ isLoading }, dispatch] = useReducer(reducer, initialState);
  return <Provider value={{ isLoading, dispatch }}>{children}</Provider>;
};

export default () => useContext(Context);


然后假设我有一个组件可以改变加载状态,但从不消耗它,如下所示:

import React from 'react';
import useLoading, { actionCreators } from 'hooks/useLoading';

export default () => {
  const { dispatch } = useLoading();
  dispatch(actionCreators.setLoadingOn();
  doSomethingAsync().then(() => dispatch(actionCreators.setLoadingOff()))
  return <React.Fragment />;
};


根据 useReducer 文档,调度具有稳定的身份。我将此解释为,当组件从 useReducer 提取调度时,当连接到该调度的状态发生更改时,它不会重新渲染,因为对调度的引用将始终相同。基本上,调度可以“像静态值一样对待”。

然而,当这段代码运行时,dispatch(actionCreators.setLoadingOn()) 行触发对全局状态的更新和 useLoading钩子(Hook)再次运行,dispatch(actionCreators.setLoadingOn()) 也是如此。 (无限重新渲染-_-)

我没有正确理解 useReducer 吗?还是我正在做的其他事情可能会导致无限重新渲染?

最佳答案

第一个问题是你不应该在渲染时触发任何 React 状态更新,包括 useReducersdispatch()useState的二传手。

第二个问题是,是的,dispatch while 总是导致 React 排队状态更新并尝试调用 reducer,如果 reducer 返回一个新值,React 将继续重新渲染。无论您从哪个组件派发 - 导致状态更新和重新渲染是 useReducer 的重点首先。

“稳定的身份”意味着 dispatch变量将指向跨渲染的相同函数引用。

关于javascript - 为什么 useReducer 的调度会导致重新渲染?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60012198/

相关文章:

javascript - 无限滚动php发帖重复

javascript - 将数组转换为 typescript 中的索引对象

javascript - 通过 javascript 按名称(在方括号中)引用 HTML 元素

javascript - 这行代码在 react 方法中做什么

javascript - 可以将 Immutable.js Map 转换为 React 组件内的对象吗

reactjs - 尝试导入错误: does not contain a default export

javascript - 使用 Redux 验证用户的流程

javascript - 用于 React 组件状态的 ImmutableJS

javascript - 如何在 reduxjs 中设计独立模块?

css - reactjs 背景图像未全屏显示