我想将此生命周期方法重写为一个钩子:
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)
,它仍然无法正常工作。
答案 0 :(得分:0)
您可以使用第二个参数(变量数组)限制useEffect触发的时间。
useEffect(() => true, [variable]);
在第一次加载时或当变量更改值时,将触发使用效果,如果您未指定任何内容作为第二个参数,则每次重新渲染useEffect都会触发。
答案 1 :(得分:0)
要将componentDidUpdate
替换为useEffect
钩子,请将其第二个参数传递给变量数组,该变量必须从此渲染更改为下一个变量,以使钩子运行
useEffect(() => {
// your code
},[props.notifications])
答案 2 :(得分:0)
问题夫妇我可以通过您的Hook代码看到一个问题:
usePrevious
永远不会更新超出第一个值集
在useEffect
中未设置任何依赖项时,它将仅运行一次。在您的情况下,由于要跟踪最后一个值集,因此需要使它成为useEffect
的依赖项,即useEffect(() => ..., [value])
,这将强制回调重新运行并更新引用。 / strike>
结果我误解了功能组件重新渲染时,它重新运行了挂钩的效果,您可以忽略第1点。
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]);