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;
>Solution :
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!