I'm trying to figure out how to use react hooks to hide or show a ponent based on an onChange event (a selected option being selected in a form).
I have a ponent called Animal, which will be hidden until someone selects 'animals' from a select menu in a form.
This is what I have tried to make:
import React, { useState, useEffect } from "react";
import useForm from "react-hook-form";
import { withRouter } from "react-router-dom";
import Select from "react-select";
import Animal from "./tips/Animal";
const specialFeatures = [
{ value: "animals", label: "Animals" },
{ value: "none", label: "None of these apply" }
];
const Method = props => {
const { register, handleSubmit, setValue, errors, reset } = useForm();
const [valuesSpecialFeatures, setSpecialFeatures] = useState([]);
const [showAnimal, setShowAnimal] = useState(false);
const handleMultiChangeSpecialFeatures = selectedOption => {
setValue("specialFeatures", selectedOption, true);
setSpecialFeatures(selectedOption);
if selectedOption === 'animals' setAnimal(!<Animal />)
};
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<label>Does this proposal incldue any of these features?</label>
<Select
className="reactSelect"
name="specialFeatures"
placeholder="Select at least one"
value={valuesSpecialFeatures}
options={specialFeatures}
onChange={handleMultiChangeSpecialFeatures}
isMulti
/>
{ showAnimal && "animals" <Animal /> }
<input type="submit" value="next" />
</form>
</div>
);
};
export default withRouter(Method);
I'm trying to test if the form field named specialFeatures has a selectedOption that includes the value 'animals', then if it does, I want to display the Animal ponent beneath that field.
This attempt is clearly incorrect, but I can't see how to set the useEffect to toggle visibility.
I'm trying to figure out how to use react hooks to hide or show a ponent based on an onChange event (a selected option being selected in a form).
I have a ponent called Animal, which will be hidden until someone selects 'animals' from a select menu in a form.
This is what I have tried to make:
import React, { useState, useEffect } from "react";
import useForm from "react-hook-form";
import { withRouter } from "react-router-dom";
import Select from "react-select";
import Animal from "./tips/Animal";
const specialFeatures = [
{ value: "animals", label: "Animals" },
{ value: "none", label: "None of these apply" }
];
const Method = props => {
const { register, handleSubmit, setValue, errors, reset } = useForm();
const [valuesSpecialFeatures, setSpecialFeatures] = useState([]);
const [showAnimal, setShowAnimal] = useState(false);
const handleMultiChangeSpecialFeatures = selectedOption => {
setValue("specialFeatures", selectedOption, true);
setSpecialFeatures(selectedOption);
if selectedOption === 'animals' setAnimal(!<Animal />)
};
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<label>Does this proposal incldue any of these features?</label>
<Select
className="reactSelect"
name="specialFeatures"
placeholder="Select at least one"
value={valuesSpecialFeatures}
options={specialFeatures}
onChange={handleMultiChangeSpecialFeatures}
isMulti
/>
{ showAnimal && "animals" <Animal /> }
<input type="submit" value="next" />
</form>
</div>
);
};
export default withRouter(Method);
I'm trying to test if the form field named specialFeatures has a selectedOption that includes the value 'animals', then if it does, I want to display the Animal ponent beneath that field.
This attempt is clearly incorrect, but I can't see how to set the useEffect to toggle visibility.
Share Improve this question asked Nov 21, 2019 at 19:38 MelMel 2,71531 gold badges135 silver badges312 bronze badges 1-
1
What is this part about?
setAnimal(!<Animal />)
. There is nosetAnimal
in your code, and can't you just set tofalse
?!<Animal />
is a forced conversion to boolean. Will always asserts tofalse
– Dupocas Commented Nov 21, 2019 at 19:54
1 Answer
Reset to default 5First of all you need to set showAnimal
state to a boolean and then use that to either show or hide the ponent:
const Method = props => {
const { register, handleSubmit, setValue, errors, reset } = useForm();
const [valuesSpecialFeatures, setSpecialFeatures] = useState([]);
const [showAnimal, setShowAnimal] = useState(false);
const handleMultiChangeSpecialFeatures = selectedOption => {
setValue("specialFeatures", selectedOption, true);
setSpecialFeatures(selectedOption);
setShowAnimal(selectedOption.some(option => option.value === "animals")); // Toggle 'showAnimal'
};
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<label>Does this proposal incldue any of these features?</label>
<Select
className="reactSelect"
name="specialFeatures"
placeholder="Select at least one"
value={valuesSpecialFeatures}
options={specialFeatures}
onChange={handleMultiChangeSpecialFeatures}
isMulti
/>
{showAnimal && <Animal />} // Render ponent based on the toggle
<input type="submit" value="next" />
</form>
</div>
);
};
There's a simpler alternative though, which doesn't involve setting the value to the state, you can just derive it during render instead:
const Method = props => {
const { register, handleSubmit, setValue, errors, reset } = useForm();
const [valuesSpecialFeatures, setSpecialFeatures] = useState([]);
const handleMultiChangeSpecialFeatures = selectedOption => {
setValue("specialFeatures", selectedOption, true);
setSpecialFeatures(selectedOption);
};
// Derive the value based on the value of `valuesSpecialFeatures`
const isAnimalSelected = valuesSpecialFeatures.some(
option => option.value === "animals"
);
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<label>Does this proposal incldue any of these features?</label>
<Select
className="reactSelect"
name="specialFeatures"
placeholder="Select at least one"
value={valuesSpecialFeatures}
options={specialFeatures}
onChange={handleMultiChangeSpecialFeatures}
isMulti
/>
{isAnimalSelected && <Animal />} // Use derived value to render ponent
<input type="submit" value="next" />
</form>
</div>
);
};