reactjs - 无法使该消息 Hook 在 React 中工作

标签 reactjs react-hooks material-ui

我正在尝试为我的组件提供一个 useMessage Hook 。

在我的应用程序中,Panel 是最大的组件,即母组件,其中有一个 Message 组件,该组件使用 Material UI 的 Snackbar code> 显示消息和警报。

这是一个code sandbox

组件以这种方式使用我的钩子(Hook):

import useMessage from './useMessage'

const SomeComponent = () => {
     const { success, error } = useMessage()

     return <button onClick={success('some message')}>Show success</button>
}

但是,它不会改变严重性,而且很多时候消息都是空的。它没有按照我期望的方式工作。

如何修复它?

最佳答案

问题

看来 useMessage Hook 中的 useEffect Hook 是所有问题的根源,特别是它与 hide 函数的交互。

const hide = () => {
  setIsMessageShown(false);
};

...

useEffect(() => {
  if (message && severity) {
    setIsMessageShown(true);
  }
  return () => {
    if (isMessageShown === false) {
      setMessage(null);
      setSeverity(null);
    }
  };
}, [
  message,
  setMessage,
  severity,
  setSeverity,
  isMessageShown,
  setIsMessageShown
]);

当调用 hide 时,它会排队状态更新以将 isMessageShown 状态切换为 false。 isMessageShownuseEffect 的依赖项,并且有一个条件检查是否存在真实的消息严重性状态。因为这也没有被清除,所以另一个状态更新被排队以将 isMessageShown 状态切换回 true。同时,useEffect Hook 返回一个清理函数,然后将状态更新排入队列以清除 messageseverity 状态,但是 >SnackbarAlert 组件仍然显示。

从现在开始似乎存在状态同步问题,这就是为什么警报在第一次调用后不起作用的原因。

解决方案

注释掉或删除 useEffect Hook 似乎可以完全解决您在codesandbox中描述和重现的问题。

这是更新的 useMessage Hook 。

import { usePanel } from "./PanelContext";

const useMessage = () => {
  const { setIsMessageShown, setMessage, setSeverity } = usePanel();

  const show = (data, action, type) => {
    if (data && data.message) {
      data = data.message;
    }
    setMessage(data);
    setSeverity(type);
    setIsMessageShown(true);
  };

  const success = (data, action) => {
    show(data, action, "success");
  };

  const info = (data, action) => {
    show(data, action, "info");
  };

  const warning = (data, action) => {
    show(data, action, "warning");
  };

  const error = (data, action) => {
    show(data, action, "error");
  };

  const hide = () => {
    setIsMessageShown(false);
  };

  return {
    success,
    info,
    warning,
    error,
    show,
    hide
  };
};

export default useMessage;

我做了一些重构来集中面板上下文代码和逻辑

PanelContext.js

import React, { useContext, useState } from "react";

export const PanelContext = React.createContext();

export const usePanel = () => useContext(PanelContext);

const PanelProvider = ({ children }) => {
  const [isMessageShown, setIsMessageShown] = useState();
  const [message, setMessage] = useState();
  const [severity, setSeverity] = useState();

  return (
    <PanelContext.Provider
      value={{
        isMessageShown,
        setIsMessageShown,
        message,
        setMessage,
        severity,
        setSeverity
      }}
    >
      {children}
    </PanelContext.Provider>
  );
}

export default PanelProvider;

Edit cant-make-this-message-hook-work-in-react

关于reactjs - 无法使该消息 Hook 在 React 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72640471/

相关文章:

javascript - React UseState钩子(Hook),无法连接数组

javascript - MUI Material-UI DatePicker格式化和设置默认值问题

javascript - React 组件在不同 DOM 节点中的交互性(并行)

javascript - react 应用程序中 pdfjs-dist 的附加加载器?

javascript - 使用 React 隐藏组件

javascript - React、点击事件和 Material-ui

reactjs - Material ui 中带有自定义输入的下拉菜单

reactjs - react 路由器更改了 URL,但未呈现组件

javascript - 在 useEffect 钩子(Hook)中添加依赖导致死循环

reactjs - 如何使用 React Hooks 将带有构造函数的类转换为功能组件?