简体   繁体   中英

Redux: How do I dispatch action in useEffect only once?

I have a calendar app where a user can upload 1 - 4 images for each calendar page.

Expected Result: When a user uploads a image with bad quality, I have a quality warning toast that should appear once for each image.

Current Result: Right now the action showToast within the useEffect is triggered multiple times. So eg when I upload a new image, delete another image, etc. everytime this quality warning is triggered again.

My Approach: I have tried to implement a local state in order to toggle a boolean ( if warning was shown once, set to false ). But I could only get it to work for all images (as soon as any image has bad quality, the local state is set to false). But I need it to be image specific.

If the quality warning for the specific image has been shown, then don't show it again.

Code:

export const useShowPoorImageQualityToast = (spreadId: string): void => {
    const dispatch = useDispatch();

    const [qualityToastIsShown, setQualityToastWasShown] = useState(false); // my approach

    const poorQualityContentIds = useSelector(
        (state: AppState) =>
            spreadWithImageContentsSelector(state, spreadId).filter((contentId) => {
                const qualityInformation = productImageQualitySelector(state, contentId);

                return qualityInformation !== undefined && qualityInformation.hasPoorQuality
            }),
        shallowEqual
    );

    useEffect(() => {
        const imageQualityWarningToast: ClosableToast = {
            mode: ToastMode.CLOSABLE,
            text: locale.photoQualityWarning.toast,
            severity: ToastSeverity.WARN,
            closable: false,
        };

        if (poorQualityContentIds.length > 0 && qualityToastIsShown === false) {

            dispatch(showToast(ToastType.NONE, imageQualityWarningToast));

            setQualityToastWasShown(!qualityToastIsShown); // my approach
        }
    }, [dispatch, poorQualityContentIds, qualityToastIsShown]);
};

I have worked on this kind of problem before, but I think it's not the most optimal one.

So what I did was instead of storing just one boolean, I stored the image id or some referrence for each image and then check that boolean stored inside that image id. This way you are only setting the flag for one specific image each time and only checking for that.

So, store something like this in your local state:

{
  image1: { warningShown: true },
  image2: { warningShown: false }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM