Conditional rendering with hooks

Viewed 661

The context : I try to build a form with hooks and render component depending on the step we are.

Problem : I have this message : "Error: UserFormHooks(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null."

I know the code work with class but no with hooks.

What I tried : I tried to put them in a ternary but it doesn't work either.

Code :

import React, { useState } from "react";
import FormUserDetails from "./FormUserDetails";
import FormPersonalDetails from "./FormPersonalDetails";
import Confirm from "./Confirm";
import Success from "./Success";

const UserFormHooks = () => {
  const [data, setData] = useState({
    step: 1,
    firstName: "",
    lastName: "",
    email: "",
    occupation: "",
    city: "",
    bio: "",
  });

  // Proceed to next step
  const nextStep = () => {
    setData(step + 1);
  };

  // Go back to prev step
  const prevStep = () => {
    setData(step - 1);
  };

  // Handle fields change
  const handleChange = (input) => (e) => {
    setData({ [input]: e.target.value });
  };

  const { step } = { data };
  const { firstName, lastName, email, occupation, city, bio } = { data };
  const values = { firstName, lastName, email, occupation, city, bio };

  switch (step) {
    case 1:
      return (
        <div>
          <FormUserDetails
            nextStep={nextStep}
            handleChange={handleChange}
            values={values}
          />
        </div>
      );
    case 2:
      return (
        <div>
          <FormPersonalDetails
            nextStep={nextStep}
            prevStep={prevStep}
            handleChange={handleChange}
            values={values}
          />
        </div>
      );
    case 3:
      return (
        <Confirm nextStep={nextStep} prevStep={prevStep} values={values} />
      );
    case 4:
      return <Success />;
    default:
      console.log("This is a multi-step form built with React.");
  }
};

export default UserFormHooks;
4 Answers

You need to fix following problems in your code:

  1. setData() will overwrite the existing state instead merging the new state with the previous state. So, make sure you pass the previous state as well when calling setData()

    setData({ ...data, step: step + 1 });
    
  2. You are not destructuring correctly. You are creating a new object with data property which leads to step being undefined and hence default case of switch statement executes. Since you are not returning anything from default case, an error is thrown because you must always return something from your component.

    const { step } = data;
    const { firstName, lastName, email, occupation, city, bio } = data;
    
  3. make sure you return something from the default case of switch statement

As the message suggests, you need to return JSX from a component. Alternatively you need to return null if no JSX is returned:

default:
   console.log("This is a multi-step form built with React.");
   return null;

You're overwriting the default state with setData(step + 1) This will set the state to a single number instead of updating the step value inside the object you specified inside useState.

To update the state and keep the current properties you can use the prevState with the setState.

prevState like the name suggests holds the previous state which in your case is the object from useState.

setData((prevState) => ({
 ...prevState,
 step: prevState.step + 1,
}));

You need to use updater function when use setData

setData(prevState => ({
            ...prevState,
            [name]: value
        }));

Hooks with objects works differently, compared to normal setState in Component Class

Related