Search code examples
reactjsreduxnext.jsredux-toolkit

Redux dispatch in useEffect causes numerous redux errors


Edit - Fixed The problem was absolute garbage redux code as it was my first time using it. I studied Redux and rewrote my code and it works fine. It wasn't working because there was way too much garbage code working at once.

I'm using nextJS and when visiting a shared URL such as /username/p/postID I want to display the initial post modal/popover.

    async function presentInitialPost(postID: string) {
        const postSnap = await db.collection("posts").doc(postID).get();
        const postData = postSnap.data();
        if(postData){
            dispatch(showModalPostView(postData as Post));
        }
    }

    useEffect(() => {
        if(initialPostID){
            presentInitialPost(initialPostID)
        }
    }, [initialPostID])

Errors (there ae numerous of each): "You may not unsubscribe from a store listener while the reducer is executing." "You may not call store.getState() while the reducer is executing."

I use the same dispatch throughout my app just fine - and if I call presentInitialPost on a button click instead - it works completely fine.

I've tried delays and debugging where the error is coming from but I haven't figured it out at all, any help is appreciated, thank you.

Redux code:

showModalPostView(state, action) {
  state.showModalPostViewFunction(action.payload);
},

setShowModalPostViewFunction(state, action) {
  state.showModalPostViewFunction = action.payload;
  return state;
},

showModalPostViewFunction: (post: Post) => {},

showModalPostViewFunction comes from my overlay wrapper component

    showModalPostView = (post: Post) => {
        console.log(this.state)
        this.setState({
            showModalPostView: true,
            modalPostViewPost: post,
        });
    };

When the modal post view is shown here, it contains multiple useSelectors which cause the errors - but only when i present the modal post view in useEffect - it works just fine throughout the app when dispatched through a click action.

In modal post view various selectors throw the errors:

const likedPosts = useSelector((state: ReduxRootState) => state.likedPosts);

Solution

  • It appears you are not using redux the way it was intended to be used. What you pass to dispatch() is supposed to be an action. A reducer receives that action and returns new state, and then then new state is sent to your subscriber (the React component).

    You are instead calling a function showModalPostView which is calling some setState function in the parent component and is returning who knows what. That return value is being passed as an argument dispatch, which kicks off a reducer. However, that setState is likely causing your child component to unsubscribe from the store so it can re-render.

    It like you aren't actually dispatching an action; you're just calling a function, so you shouldn't be using dispatch at all.

    async function presentInitialPost(postID: string) {
        const postSnap = await db.collection("posts").doc(postID).get();
        const postData = postSnap.data();
        if(postData){
            showModalPostView(postData as Post);
        }
    }