componentDidUpdate转换为挂钩

时间:2019-07-12 09:47:39

标签: reactjs react-redux material-ui react-hooks

我想将此生命周期方法重写为一个钩子:

componentDidUpdate = prevProps => {
    const { notifications, popNotification } = this.props;

    if (prevProps.notifications.length >= notifications.length) return;

    const [notification] = notifications;
    popNotification(notification.id);
    this.setState({
        open: true,
        message: notification.text,
        variant: notification.variant,
    });
};

我知道我必须使用useEffect钩子,但是直到现在它都没有起作用。这是我到目前为止提出的:

function usePrevious(value) {
    const ref = useRef();
    useEffect(() => {
        ref.current = value;
    });
    return ref.current;
}

const dispatch = useDispatch();
const popMessage = useCallback(id =>
    dispatch(NotificationActions.popNotification(id))
);

const notifications = useSelector(state => state.notifications);
const previousValue = usePrevious(notifications.length);

useEffect(() => {
    if (previousValue >= notifications.length) return;

    // Extract notification from list of notifications
    const [notification] = notifications;
    popMessage(notification.id);
    // Open snackbar
    setSnackbar({
        open: true,
        message: notification.text,
        variant: notification.variant,
    });
});

此尝试不像旧方法那样起作用,它比旧方法被调用更多,并且抛出TypeError: notification is undefined。此外,如果我在提取通知之前添加了if (notifications.length > 0),它仍然无法正常工作。

3 个答案:

答案 0 :(得分:0)

您可以使用第二个参数(变量数组)限制useEffect触发的时间。

useEffect(() => true, [variable]);

在第一次加载时或当变量更改值时,将触发使用效果,如果您未指定任何内容作为第二个参数,则每次重新渲染useEffect都会触发。

答案 1 :(得分:0)

要将componentDidUpdate替换为useEffect钩子,请将其第二个参数传递给变量数组,该变量必须从此渲染更改为下一个变量,以使钩子运行

useEffect(() => {

  // your code

},[props.notifications])

答案 2 :(得分:0)

问题夫妇我可以通过您的Hook代码看到一个问题:

  1. usePrevious永远不会更新超出第一个值集

    useEffect中未设置任何依赖项时,它将仅运行一次。在您的情况下,由于要跟踪最后一个值集,因此需要使它成为useEffect的依赖项,即useEffect(() => ..., [value]),这将强制回调重新运行并更新引用。 / strike>

    结果我误解了功能组件重新渲染时,它重新运行了挂钩的效果,您可以忽略第1点。

  2. useEffect中的主要更新代码(与第1点类似)仅运行一次。

    同样,当通知计数更改时,预计代码将重新运行,因此需要将其设置为依赖项useEffect(() => ..., [notifications.length])

对于您提到的错误-notification is undefined,这表明您的notifications状态不是有效数组或该数组为空,请检查useSelector(state => state.notifications)的结果

这就是我希望它根据您的代码显示的样子

const dispatch = useDispatch();
const popMessage = useCallback(id =>
  dispatch(NotificationActions.popNotification(id))
, []);

const notifications = useSelector(state => state.notifications);
const previousValue = usePrevious(notifications.length);

useEffect(() => {
  if (!notifications.length || previousValue >= notifications.length) return;

  // Extract notification from list of notifications
  const [notification] = notifications;
  if (!notification) return;

  popMessage(notification.id);
  // Open snackbar
  setSnackbar({
    open: true,
    message: notification.text,
    variant: notification.variant,
  });
}, [notifications]);