Next.js Discord

Discord Forum

Server side pre-rendering of interactive components

Unanswered
West African Lion posted this in #help-forum
Open in Discord
West African LionOP
Help Noob
I have an registration form split between different models and is navigated using breadcrumb style. It has client side simple data validation and is passing form data to server side on submit. I am using Next.JS 14 and tailwind CSS only frontend no backend, and local storage for state and data persistence. what I want to do is to pre-build every text and input fields on server side in build time and then it can become interactive/hydrate on client side on runtime.

Using app directory and 'use client' for to use browser APIs such as useLocalStorage, useEffect, useState etc

pages.js -> demo.js -> different parts/models of the form

How do I do that ?

24 Replies

West African LionOP
If I check the performance of my webpage using the dev tools, I can observe that my Header is rendering first and the my form is rendering with delay of couple of 100ms. This is something I want to avoid and can't do so
West African LionOP
Yes
I am using custom made vanilla breadcrumb navigation so I have separate components for each.
One component for email, one for names, address , phone and password. All separate components
@B33fb0n3 you can render them in parallel when you create a [parallel route](https://nextjs.org/docs/app/building-your-application/routing/parallel-routes). Like that you can split different parts from your app and render them in parallel
West African LionOP
How do we do parallel rendering?
Can you please link something.
Also I commented out the code that handled the local storage part and the delayed rendering has seemed to be vanished. Why is that ?
@West African Lion How do we do parallel rendering? Can you please link something. Also I commented out the code that handled the local storage part and the delayed rendering has seemed to be vanished. Why is that ?
some parts inside my message are already links. You can see that, when the specific text is blue like a link: (see attached). The full link is: https://nextjs.org/docs/app/building-your-application/routing/parallel-routes
West African LionOP
Apologies for not noticing.
West African LionOP
Do you have any feedback on later part of the reply ?
How do you import the part with the localstorage?
West African LionOP
const [formData, setFormData] = useState({});
  const [currentStep, setCurrentStep] = useState(1);
  const [isMounted, setIsMounted] = useState(false);

  // Load initial data from localStorage after the component has mounted
  useEffect(() => {
    if (typeof window !== "undefined") {
      const savedData = localStorage.getItem("formData");
      const savedStep = localStorage.getItem("currentStep");

      if (savedData) setFormData(JSON.parse(savedData));
      if (savedStep) setCurrentStep(parseInt(savedStep, 10));

      // Indicate the component has mounted to prevent hydration issues
      setIsMounted(true);
    }
  }, []);

  // Save formData to localStorage whenever it updates
  useEffect(() => {
    if (isMounted) {
      localStorage.setItem("formData", JSON.stringify(formData));
    }
  }, [formData, isMounted]);

  // Save currentStep to localStorage whenever it updates
  useEffect(() => {
    if (isMounted) {
      localStorage.setItem("currentStep", currentStep);
    }
  }, [currentStep, isMounted]);

const handleInputChange = (e) => {
    let name, value;
    if (e.target) {
      // If it's an event object
      ({ name, value } = e.target);
    } else {
      // If it's a direct update
      ({ name, value } = e);
    }
    setFormData({
      ...formData,
      [name]: value,
    });
  };

  if (!isMounted) return null;

  const nextStep = () => setCurrentStep(currentStep + 1);
  const prevStep = () => setCurrentStep(currentStep - 1);
West African LionOP
page.js
import Header from "./header";
import Demo from "./components/demo";

export default function Home() {
  return (
    <div>
      <Header />
      <Demo />
      <Footer /> 
    </div>
  );
}
I think the problem occurs if I use the isMounted condition because it takes a few milliseconds to check and see if there is anything in the local storage.
@West African Lion I think the problem occurs if I use the isMounted condition because it takes a few milliseconds to check and see if there is anything in the local storage.
the localStorage is only available clientside. So it can't be prerendered by the server and hydrated on client (thats what 'use client' does). So it waits for the client to hydrate (the delay you experience) and shows then the actual data
I wouldn't try localstorage to store data for the "fast" initial data show
West African LionOP
What is recomended to persist data throughout the form ?
@West African Lion What is recomended to persist data throughout the form ?
Use a database and save stuff there. That's the idea of a database
@West African Lion which message solved your initial issue the most?
West African LionOP
None
Actually it was the issue of using the isMounted condition and shifting from defined components to undefined components
West African LionOP
Skill issue
Better error handling
Lack of experience
you might want to read this: https://nextjs-forum.com/post/1138338531983491154#message-1138338531983491154 so I will be able to help you with better error handling.
West African LionOP
Thank you