0

I have two pages in a Next.js project, in the first one the user fills out a form to create a post, that info gets stored in a JSON object that has to be passed to the second page so the user can see a preview of the post and if he/she likes it, the post gets created.

The object is a little to big to be passed as query parameters (it has around 25 elements in it) but I can't find how to pass it to the second page props.

The function that gives the object it's values looks like this

async function submitHandler(event) {
event.preventDefault();
validateAndSetEmail();
validateAndSetTitle();
validateAndSetSalary();
if (isFormValidated === true) {
  // this checks if the user has created another post 
  const finalPostData = await checkExistence(Email);
  if (finalPostData["user"] === "usernot found") {
    setPostData({
      title: Title,
      name: Name,
      city: City,
      email: Email,
      type_index: TypeNumber,
      type: Type,
      region_index: regionNumber,
      region: region,
      category_index: categoryNumber,
      category: category,
      range: Range,
      highlighted: highlighted,
      featured: featured,
      show_logo: showLogo,
      show_first: showFirst,
      description: Description,
      price: basePrice + cardPrice,
      website: Website,
      logo: Logo,
      application_link: applicationLink,
      time_to_pin: weeksToPin,
      pin: pin,
      post_to_google: shareOnGoogle,
    });
  } else {
    setPostData({
      // set other values to the object
    });
  }
    // Here I want to do something like 
       router.push({
         pathname: "/preview/",
         post: PostData,
       });
  
}
}

The second page looks something like this:

export default function PreviewPage(props) {
const item = props.postInfo; // <= I want item to recieve the JSON object from the other page

  return (
    <Fragment>
      <Navbar />

      <div className="flex inline mt-12 ml-24">
        <Card
          category={item.category}
          Name={item.company}
          logo={item.logo}
          City={item.company_city}
          Website={item.company_website}
        />
        <Description
          title={item.job_title}
          description={item.description}
          category={item.category}
          region={item.region}
          Type={item.type}
          Link={item.link}
        />
      </div>
      <Footer />
    </Fragment>
  );
}
Jaime Ortiz
  • 1,089
  • 10
  • 14
  • can you also post the form page and if you are using a router, can you post how that is set up? – knicholas Jan 06 '22 at 22:33
  • The form page is like 1k lines, would the function that sets the object values be enough? also, I am not using a router, up until now, i was just using next's folder navigation – Jaime Ortiz Jan 06 '22 at 22:44
  • 1
    Possible solution here -> https://stackoverflow.com/questions/66267441/how-can-i-pass-data-in-multi-step-forms-in-nextjs – MB_ Jan 06 '22 at 22:55
  • Thank you, I will try it out in a moment – Jaime Ortiz Jan 06 '22 at 23:49
  • I'd recommend you have a look into [React Context](https://reactjs.org/docs/context.html) or any third-party React state management library. – juliomalves Jan 08 '22 at 17:49

2 Answers2

0

Try

 router.push({
         pathname: "/preview/",
         query: PostData,
       });
export default function PreviewPage() {
const router = useRouter()
const item = router.query
knicholas
  • 520
  • 4
  • 10
  • This does work. I get the info on the preview page, but, is it a good idea to pass all that information into the url? – Jaime Ortiz Jan 06 '22 at 23:48
  • 2
    @JaimeOrtiz the only other solution is to use a state management tool like Redux [example](https://dev.to/waqasabbasi/server-side-rendered-app-with-next-js-react-and-redux-38gf) or React Context [example](https://webdevstudios.com/2021/05/04/sharing-data-in-next-js-with-react-context/) – knicholas Jan 07 '22 at 06:35
0

After looking into React Context and Redux thanks to knicholas's comment, I managed to find a solution.

Created a context provider file

I create the Context with 2 things inside:

  1. An empty object representing the previewData that will be filled later

  2. A placeholder function that will become the setter for the value

    import React from "react";
    
    const PreviewContext = React.createContext({
      Previewdata: {},
      setPreviewData: (data) => {},
    });
    
    export default PreviewContext;
    

Then in _app.js

Create a useState instance to store the previewData and have a funtion to pass to the other pages in order to set the value when the form is filled, then, wrap the component with the context provider

function MyApp({ Component, pageProps }) {
  const [previewData, setPreviewData] = useState({});
  return (
    <div className="">
      <PreviewContext.Provider value={{ previewData, setPreviewData }}>
        <Component {...pageProps} />
      </PreviewContext.Provider>
    </div>
  );
}

export default MyApp;

In the form page

I get the function to set the value of previewData by using of useContext();

const { setJobPreviewData } = useContext(jobPreviewContext);

With that the value for previewData is available everywhere in the app

Jaime Ortiz
  • 1,089
  • 10
  • 14