Next.js Discord

Discord Forum

Accessing zustand state in server action

Unanswered
Weevil parasitoid posted this in #help-forum
Open in Discord
Weevil parasitoidOP
Hey guys I am making an application like reddit and I wrote a function to create a new community. When the user submits the form I want to pass the info provided by the user but I also want to pass the userID of the current user which is stored in a zustand store and then the community is created in the backend. Then the backend returns the current user but the id of the new community is added to the user. Then I want to update the user state stored in the Zustand store. The apprach that i tried was accessing the zustand state and function in a client action and then passing themm to the server action but I get this error 'Error: (0 , _userWEBPACK_IMPORTED_MODULE_5.getUser) is not a function'. How can I solve this? Please help

9 Replies

Weevil parasitoidOP
'use server';

import axios from "axios";
import { redirect } from "next/navigation";
import { uploadImage } from "./cloudinary";
import { getUser, loginUser } from "./user";

export async function createCommunity(prevState, formData) {
    const user = getUser();
    const name = formData.get('name');
    const description = formData.get('description');
    const banner = formData.get('banner');
    const logo = formData.get('logo');

    console.log(banner);
    console.log(logo);

    if (!name || name.trim().length === 0) {
        return { error: "Name of the community cannot be blank." }
    }
    if (!description || description.trim().length === 0) {
        return { error: "Description cannot be blank." }
    }

    const bannerURL = await uploadImage(banner);
    const logoURL = await uploadImage(logo);

    const community = {
        bannerURL: bannerURL,
        logoURL: logoURL,
        name: name,
        description: description,
        userID: user.id
    };

    const response = await axios.post('http://localhost:8000/createCommunity', { ...community }, {
        headers: {
            'Content-Type': 'application/json'
        }
    });

    if (response.status != 200) {
        throw new Error("Please try again later.");
    }
    else {
        const data = response.data;
        if (data.message != 'success') {
            return { error: data.message }
        }
        else {
            loginUser(data.user);
            redirect('/');
        }
    }
}

This is the action that takes place when the form is submitted

'use client';

import { userStore } from "@/zustand/store";

export function getUser() {
    'use client';
    const state = userStore.getState();

    return state.user;
}

export function loginUser(user) {
    'use client';
    const state = userStore.getState();
    state.loginUser(user);
}

This is the client action
Sun bear
You cant access userStore from the server.

createCommunity is a server funcrion and getUser is a client function.

I think you should write an additional function like getUserServerSide() and think about how to do it
When you show your zustand userStore.getState() then its possible to see how to addapt it for a serverside function
@Sun bear When you show your zustand userStore.getState() then its possible to see how to addapt it for a serverside function
Weevil parasitoidOP
So what would getUserServerSide() be like?
Any ideas?
@Weevil parasitoid So what would getUserServerSide() be like?
Sun bear
It depends on what your current getUser function looks like.

You could also pass the user from the client to the server function.

createCommunity(user,...)

But thats not really secure imo. How do you do authentication? I think only logged in users are allowed to create communities you should be able to get the user serverside anyway to build an apllication like that
@Sun bear It depends on what your current getUser function looks like. You could also pass the user from the client to the server function. `createCommunity(user,...)` But thats not really secure imo. How do you do authentication? I think only logged in users are allowed to create communities you should be able to get the user serverside anyway to build an apllication like that
Weevil parasitoidOP
Yeah you are right but the problem is that I have to update the logged in user on the client side since if a person creates a community he automatically follows. For that I need to use a function from zustand store that's why I tried this approach. But it seems like i have to do it elsewhere. But getting the logged in user's if is not a problem.
@Sun bear It depends on what your current getUser function looks like. You could also pass the user from the client to the server function. `createCommunity(user,...)` But thats not really secure imo. How do you do authentication? I think only logged in users are allowed to create communities you should be able to get the user serverside anyway to build an apllication like that
Weevil parasitoidOP
Hey so i managed to fix it i made the createCommunity function into a client action. The reason why I made it a server action in the first place was beacuse I had to upload images and fs can only be used in server actions and I couldn't pass the image from a client action to server action which is my cloudinary function. So as a workaround I passed the whole formdata to the cloudinary function. Then i was able to access the zustand store. Also eventually i had to make this a client action as I had to pass the auth cookies to my backend for validation.
export async function createCommunity(prevState, formData) {
    const name = formData.get('name');
    const description = formData.get('description');
    const banner = formData.get('banner');
    const logo = formData.get('logo');
    const state = userStore.getState();

    console.log(banner);
    console.log(logo);

    if (!name || name.trim().length === 0) {
        return { error: "Name of the community cannot be blank." }
    }
    if (!description || description.trim().length === 0) {
        return { error: "Description cannot be blank." }
    }

    // const bannerURL = await uploadImage(banner);
    // const logoURL = await uploadImage(logo);

    const imageURLs = await uploadImages(formData);

    const community = {
        bannerURL: imageURLs.bannerURL,
        logoURL: imageURLs.logoURL,
        name: name,
        description: description,
    };

    const response = await axios.post('http://localhost:8000/createCommunity', { ...community }, {
        headers: {
            'Content-Type': 'application/json'
        },
        withCredentials: true
    });

    if (response.status != 200) {
        throw new Error("Please try again later.");
    }
    else {
        const data = response.data;
        if (data.message != 'success') {
            return { error: data.message }
        }
        else {
            state.loginUser(data.user);
            update();
        }
    }
}
This is the updated code