React Hook useEffect 缺少依赖项:'classes'(Material-ui 样式和 react-bootstrap-sweetalert)

React Hook useEffect has missing dependencies: 'classes' (Material-ui styles and react-bootstrap-sweetalert)

我收到此警告:“React Hook useEffect 缺少依赖项:'classes.button' 和 'classes.warning'”。

这里的问题是,根据 recommended usage of react-bootstrap-sweetalert,我应该将 SweetAlert 组件设置为状态(我不知道这是否是一个好的做法,但他们建议如何使用它)。

import { makeStyles } from "@material-ui/core/styles";
import styles from "assets/jss/views/Alerts";
const useStyles = makeStyles(styles);

export default function Alerts() {
  const [alert, setAlert] = useState(null);

  useEffect(() => {
    fetch('api').then(res => res.json()).then(data => setData(data))
      .catch(err => {

        setAlert(
          <SweetAlert
            style={{ display: "block", marginTop: "-100px" }}
            title="Error"
            onConfirm={() => {setAlert(null); setLoading(false)}}
            onCancel={() => {setAlert(null); setLoading(false)}}
            confirmBtnCssClass={classes.button + " " + classes.warning} // HERE!
          >
            error
          </SweetAlert>
        )

      })
  }, [])

  const classes = useStyles();
  return (
    <div>
     {alert}
     ...
    </div>
  )
}

我有多个警报组件,这就是他们推荐使用的原因。 我想知道解决这个问题的正确方法。

如果您在 useEffect() 之外有一个 classes 对象来保存您的按钮样式,那么您应该将 classes 对象作为依赖项传入:

useEffect(() => {
  ...
}, [classes]);

否则,您可以对按钮进行硬编码 类:

confirmBtnCssClass={'btn btn-warning'}

@EdLucas 的第一个答案是根据给定问题的正确解决方案。

当你使用 useEffect 它里面的每个状态,道具和一些函数都必须是一个依赖项,即使它永远不会改变或者它是一个函数(依赖于其他函数, props 或 state) 或者它是否经常变化。这里的问题是我们想将我们想要执行回调的内容添加到 dependencies 数组中,而不是它应该是 according to this issue.

这是关于更易于阅读的代码与防止错误。 Dan Abramov (gaearon) 的回答是:“到目前为止,根据我们的经验,由缺少依赖项引起的问题比失去快速的“[] 表示挂载”视觉快捷方式要严重得多。”这就是为什么不是关于应该执行回调的全部内容,而是关于可能导致错误的内容的原因。

这是我所做的:

const errorAlert = useCallback(
(message = 'Try again later') => {
  setAlert(
    <SweetAlert
      style={{ display: "block", marginTop: "-100px" }}
      title="Error"
      onConfirm={() => {setAlert(null); setLoading(false)}}
      onCancel={() => {setAlert(null); setLoading(false)}}
      confirmBtnCssClass={classes.button + " " + classes.warning}
    >
      {message}
    </SweetAlert>
  );
},
[classes.button,classes.warning]);

那我就可以这样用了:

useEffect(() => {
 fetch('api')
  .then(res => res.json())
  .then(data => setData(data))
  .catch(err => errorAlert())
}, [errorAlert]);

errorAlert 函数按照 React 文档的建议包装到 useCallback 中: https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies

  1. errorAlert 不能移动到 useEffect 中,因为它被其他函数使用
  2. errorAlert 不能移出组件,因为它使用 'classes'
  3. 作为最后的手段,我将 errorAlert 函数包装到 useCallback 中,以确保它不会在每次渲染时发生变化 除非 'classes.button' 和 'classes.warning' 改变(它永远不会发生)然后使用具有 应该再次执行 errorAlert 依赖项(所有这些)。