componentDidUpdate 转换为 Hooks
componentDidUpdate Conversion to 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)
,还是不行。
您可以使用第二个参数(变量数组)限制 useEffect 何时触发。
useEffect(() => true, [variable]);
在第一次加载或变量改变值时,useEffect 将被触发,如果你没有指定任何东西作为第二个参数,每re-render useEffect 将被触发。
要将 componentDidUpdate
替换为 useEffect
挂钩,请将第二个参数传递给它,其中包含一个变量数组,必须从这个渲染更改为下一个渲染,以便挂钩 [=15] =]
useEffect(() => {
// your code
},[props.notifications])
几个问题 我可以从你的 Hook 代码中看到一个问题:
usePrevious
永远不会更新超过第一个值集
如果在 useEffect
中没有设置任何依赖项,那么它 运行 只会出现一次。在你的情况下,因为你想跟踪最后一个值集,你需要使它成为 useEffect
的依赖项,即 useEffect(() => ..., [value])
,这将强制回调到 re-run 并更新 ref .
原来是我理解错了,函数组件re-renders时,re-run是hooks的效果,可以忽略第1点
useEffect
里面的主要更新代码,和第1点类似,只会运行一次。
同样,当通知计数发生变化时,代码预计会 re-run,因此需要将其设置为依赖项 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]);
我想把这个生命周期方法重写成一个钩子:
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)
,还是不行。
您可以使用第二个参数(变量数组)限制 useEffect 何时触发。
useEffect(() => true, [variable]);
在第一次加载或变量改变值时,useEffect 将被触发,如果你没有指定任何东西作为第二个参数,每re-render useEffect 将被触发。
要将 componentDidUpdate
替换为 useEffect
挂钩,请将第二个参数传递给它,其中包含一个变量数组,必须从这个渲染更改为下一个渲染,以便挂钩 [=15] =]
useEffect(() => {
// your code
},[props.notifications])
几个问题 我可以从你的 Hook 代码中看到一个问题:
usePrevious
永远不会更新超过第一个值集如果在
useEffect
中没有设置任何依赖项,那么它 运行 只会出现一次。在你的情况下,因为你想跟踪最后一个值集,你需要使它成为useEffect
的依赖项,即useEffect(() => ..., [value])
,这将强制回调到 re-run 并更新 ref .原来是我理解错了,函数组件re-renders时,re-run是hooks的效果,可以忽略第1点
useEffect
里面的主要更新代码,和第1点类似,只会运行一次。同样,当通知计数发生变化时,代码预计会 re-run,因此需要将其设置为依赖项
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]);