The question is published on by Tutorial Guruji team.
I have this problem that when I render first component based on ‘switch’ case, I get the object values (string) displayed on the screen, but when I ‘switch’ to another component on ‘button’ click, the object values (string) disappears in all the components. the values comes from a single object and are passed as props to the components. I have checked the react components on the browser and found the object values becomes undefined whenever I made the first click to move to another component. I could not figure out why this is happening. I need help. Thank you.
This is the code:
This is parent component
import React, {useState} from 'react'; import OneToFive from './questionOneToFive'; import SixToTen from './questionSixToTen'; const Signup = () => { const [fields, setFields] = useState({ step: 1, qOne: 'What is the name of your father?', qTwo: 'What is the first state you visited in Nigeria?', qThree: 'What type of phone are you using?', }); const { step } = fields; const { qOne, qTwo} = fields; const values = { qOne, qTwo} const nextStep = () => { const { step } = fields; setFields( {step : step + 1} ); } const prevStep = () => { const { step } = fields; setFields( {step: step - 1} ); } switch(step) { case 1: return ( <OneToFive nextStep={nextStep} values={values} /> ); case 2: return ( <SixToTen nextStep={nextStep} prevStep={prevStep} values={values} /> ); case 3: return <h1>Eleven to Fifteen</h1> case 4: return <h1>Sixteen to Twenty</h1> default: return <h1>Error page not found</h1> } } export default Signup;
This is the first component.
const OneToFive = ({nextStep, values}) => { const contee = (e) => { e.preventDefault(); nextStep(); } return ( <div className="bg-green-200 mx-auto my-10 w-2/4 p-10 shadow-lg shadow-green-500 rounded-lg"> <h3><span className="font-bold">Q 1:</span> {values.qOne}</h3> <div className="my-3"> <input type="radio" name="mathQOne" value="abubakar"/> <label htmlFor=""> abubakar</label> <br /> <input type="radio" name="mathQOne" value="usman"/> <label htmlFor=""> usman</label> <br /> <input type="radio" name="mathQOne" value="shehu"/> <label htmlFor=""> shehu</label> <br /> <input type="radio" name="mathQOne" value="bello"/> <label htmlFor=""> bello</label> </div> } export default OneToFive;
This is the second component
const SixToTen = ({nextStep, prevStep, values}) => { const contee = (e) => { e.preventDefault(); nextStep(); } const prev = (e) => { e.preventDefault(); prevStep(); } return ( <h3><span className="font-bold">Q 2:</span> {values.qTwo}</h3> <div className="my-3"> <input type="radio" name="mathQTwo" value="abuja"/> <label htmlFor=""> abuja</label> <br /> <input type="radio" name="mathQTwo" value="kaduna"/> <label htmlFor=""> kaduna</label> <br /> <input type="radio" name="mathQTwo" value="maiduguri"/> <label htmlFor=""> maiduguri</label> <br /> <input type="radio" name="mathQTwo" value="kano"/> <label htmlFor=""> kano</label> </div> <div className="flex flex-row gap-3"> <div className="flex flex-1 justify-start"> <button className="bg-green-500 text-white p-3 mt-10 rounded-lg shadow-sm shadow-pink-600" onClick={prev}>Previous</button> </div> <div className="flex flex-1 justify-end"> <button className="bg-green-500 text-white p-3 mt-10 rounded-lg shadow-sm shadow-pink-600" onClick={contee}>Next</button> </div> </div> </div> ) } export default SixToTen;
Answer
Your nextStep
and prevStep
functions are both replacing your original fields
state variable with an object with nothing but step
.
In other words, you start off with fields
set to:
{ step: 1, qOne: 'What is the name of your father?', qTwo: 'What is the first state you visited in Nigeria?', qThree: 'What type of phone are you using?', }
Then, when you call nextStep
, it does setFields({step: step + 1})
, so you end up with fields
being:
{ step: 2 }
I think what you want here is to change the step, but leave the other properties unchanged. Try these functions instead:
const nextStep = () => { const { step } = fields; setFields( {...fields, step: step + 1} ); }; const prevStep = () => { const { step } = fields; setFields( {...fields, step: step - 1} ); };
Using the spread operator, all properties from the fields are copied to the new value, and then the step is incremented/decremented.
You could achieve the same without the spread operator like this:
const nextStep = () => { const { step, qOne, qTwo, qThree } = fields; setFields( {step: step + 1, qOne, qTwo, qThree} ); }; const prevStep = () => { const { step, qOne, qTwo, qThree } = fields; setFields( {step: step - 1, qOne, qTwo, qThree} ); };
This is perhaps easier to understand, but it’s also more verbose, especially if you ever have more than three questions!