How do I create a file that stores states
Answered
Large oak-apple gall posted this in #help-forum
Large oak-apple gallOP
I have a Next13 React App that is connected to a mongoDB and I am trying to make a page that allows you to create a post. However, I wont be doing this in a single page. Rather it would be across multiple pages starting at:
- app/create-post/page.js
- app/create-post/step-1/page.js
- app/create-post/step-2/page.js
and so on...
The way it works is there is a page.js file in a create-post folder that has a button for when after you click it, it would send the userId to a file that would store the userId and the variables that will be created in the next step and then goes to the next page which would be a folder app/create-post/step-1/page.js. This page has a form where you can enter the title of the post and then when you hit the button, it goes to the next step which is another form where you give the post a description. After you finish the description you can hit a button that sends you to step-3. In step-3 there is a button that would then send the title, and post data to mongoDB. I am trying to create something similar to how airBnB does it to submit a house or how upwork does it to create a new job posting.
So, what I'm asking is if there is a way to store each variable title, post, and any other variable in other steps in a file which can then be sent on the final step. My description might be a little confusing so feel free to ask for clarification. Any help is appreciated, thanks!
- app/create-post/page.js
- app/create-post/step-1/page.js
- app/create-post/step-2/page.js
and so on...
The way it works is there is a page.js file in a create-post folder that has a button for when after you click it, it would send the userId to a file that would store the userId and the variables that will be created in the next step and then goes to the next page which would be a folder app/create-post/step-1/page.js. This page has a form where you can enter the title of the post and then when you hit the button, it goes to the next step which is another form where you give the post a description. After you finish the description you can hit a button that sends you to step-3. In step-3 there is a button that would then send the title, and post data to mongoDB. I am trying to create something similar to how airBnB does it to submit a house or how upwork does it to create a new job posting.
So, what I'm asking is if there is a way to store each variable title, post, and any other variable in other steps in a file which can then be sent on the final step. My description might be a little confusing so feel free to ask for clarification. Any help is appreciated, thanks!
Answered by Dayo
you probably weren't wrapping your context provider around your entry layout.js file
36 Replies
American Curl
You could look into state management libraries like Zustand. The docs even have a nextjs example https://docs.pmnd.rs/zustand/integrations/persisting-store-data#usage-in-next.js
Jotai could also be interesting. Definitely check the differences between them to fit your use case https://jotai.org/docs/guides/nextjs
Large oak-apple gallOP
So is the only way to do this is with a third party tool?
there isnt anyting I can do with just plain react?
American Curl
I assume you're using only server components, right?
Large oak-apple gallOP
not necessarily
ive been doing alot of client rendering as well
American Curl
You could also use react context https://react.dev/reference/react/createContext
and wrap it around the create-post layout
Large oak-apple gallOP
I was looking at contexts but it only works if I have a bunch of components all feeding into one page right?
American Curl
Not really. If you wrap components around a context, you can use and mutate the context anywhere you like. But that only works on client components
Large oak-apple gallOP
For instance, everything would have to feed back into my app/create-post/page.js which would look like:
<Provider>
<Step 1 />
<Step 2/>
<Step 3 />
</Provider>
<Provider>
<Step 1 />
<Step 2/>
<Step 3 />
</Provider>
American Curl
Yeah in each step you can do anything you like with the state within that context and then back in /create-post/page.js you can access it
but each component that uses the context has to be a client component
Large oak-apple gallOP
So what would that look like
Would you mind taking a look at my code?
Because Im in the process of trying useContext but its not quite working the way I had hoped
American Curl
Yeah so in
so in
postContext.js you are creating a custom hook called useCreatePostContext which makes your 3 usestates available in any client component that uses your hookso in
page.js you don't need to wrap your content in the CreatePostProvider. Instead, you import useCreatePostContext and use the hook:const { userId } = useCreatePostContext()
return <div>{userId}</div>Large oak-apple gallOP
do I have to use this: const { userId, setUserId } = useCreatePostContext();
American Curl
yeah in the destructured object you can use anything that you declare in the
value prop in your postContextLarge oak-apple gallOP
I keep getting this error: TypeError: Right side of assignment cannot be destructured
American Curl
Did you import useCreatePostContext?
Large oak-apple gallOP
Yeah this is what it looks like:
"use client";
import { useEffect, useState, useContext } from "react";
import { useRouter } from "next/navigation"; // lets us navigate to different pages
import { useCreatePostContext } from "@app/create-post/postContext"; // Our created context for post details
import Form from "@components/Form";
const CreatePost = () => {
const router = useRouter(); // router object
const { userId, setUserId } = useCreatePostContext(); // context object
return (
JSX code
};
export default CreatePost;
"use client";
import { useEffect, useState, useContext } from "react";
import { useRouter } from "next/navigation"; // lets us navigate to different pages
import { useCreatePostContext } from "@app/create-post/postContext"; // Our created context for post details
import Form from "@components/Form";
const CreatePost = () => {
const router = useRouter(); // router object
const { userId, setUserId } = useCreatePostContext(); // context object
return (
JSX code
};
export default CreatePost;
American Curl
Ah my mistake, you do have to wrap your content around the
CreatePostProvider. But you will probably have to do it in a layout.js fileI dont know if this works in the page because I think it has to be nested in order for the hook to work but not sure
Large oak-apple gallOP
So within the create-post folder, i would have to create a layout.js file as well?
American Curl
test it without first. if it doesn't work try it with a layout.js file yeah
Large oak-apple gallOP
yeah it still gives me the same error
American Curl
mh yeah hard to inspect from afar. you could try logging the hook to see what it even returns
Large oak-apple gallOP
Okay yeah I'll try a few other things
what does your
useCreatePostContext look like?Large oak-apple gallOP
This is what it looks like:
"use client";
// CreatePostContext.js
import { createContext, useState, useContext } from "react";
// Create the context
const CreatePostContext = createContext();
// Create a custom hook to use the context
export const useCreatePostContext = () => {
return useContext(CreatePostContext);
};
// Create the context provider component
export const CreatePostProvider = ({ children }) => {
const [userId, setUserId] = useState(null);
const [title, setTitle] = useState("");
const [post, setPost] = useState("");
return (
<CreatePostContext.Provider
value={{
userId,
setUserId,
title,
setTitle,
post,
setPost,
}}
>
{children}
</CreatePostContext.Provider>
);
};
"use client";
// CreatePostContext.js
import { createContext, useState, useContext } from "react";
// Create the context
const CreatePostContext = createContext();
// Create a custom hook to use the context
export const useCreatePostContext = () => {
return useContext(CreatePostContext);
};
// Create the context provider component
export const CreatePostProvider = ({ children }) => {
const [userId, setUserId] = useState(null);
const [title, setTitle] = useState("");
const [post, setPost] = useState("");
return (
<CreatePostContext.Provider
value={{
userId,
setUserId,
title,
setTitle,
post,
setPost,
}}
>
{children}
</CreatePostContext.Provider>
);
};
@Large oak-apple gall This is what it looks like:
"use client";
// CreatePostContext.js
import { createContext, useState, useContext } from "react";
// Create the context
const CreatePostContext = createContext();
// Create a custom hook to use the context
export const useCreatePostContext = () => {
return useContext(CreatePostContext);
};
// Create the context provider component
export const CreatePostProvider = ({ children }) => {
const [userId, setUserId] = useState(null);
const [title, setTitle] = useState("");
const [post, setPost] = useState("");
return (
<CreatePostContext.Provider
value={{
userId,
setUserId,
title,
setTitle,
post,
setPost,
}}
>
{children}
</CreatePostContext.Provider>
);
};
you probably weren't wrapping your context provider around your entry layout.js file
Answer
Large oak-apple gallOP
Okay thank you