I have the following useEffect hook in my functional component that I only want to use once (when the component mounts) in order to load some data from an API:
const Gear = () => {
const [weaponOptions, setWeaponOptions] = useState([
{
key: "0",
label: "",
value: "null"
}
]);
const [weapon, setWeapon] = useState("null");
useEffect(() => {
console.log("Gear.tsx useEffect");
const fetchWeaponsOptions = async (): Promise<void> => {
const weaponsData = await getWeapons();
const newWeaponOptions: DropdownOptionType[] = [
...weaponOptions,
...weaponsData.map(({ id, name }) => {
return {
key: id,
label: name,
value: id
};
})
];
setWeaponOptions(newWeaponOptions);
};
fetchWeaponsOptions();
}, []);
// TODO add weapon dropdown on change, selected weapon state
const handleWeaponChange = ({ value }: DropdownOptionType): void => {
setWeapon(value);
};
return (
<div>
<h2>Gear:</h2>
<Dropdown
defaultValue={weapon}
label="Weapon"
name="weapon"
options={weaponOptions}
onChange={handleWeaponChange}
/>
</div>
);
};
A React documentation note states that this is valid practice when you only want the effect to run on mount an unmount:
If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works.
But I am getting the following create-react-app linter warning:
35:6 warning React Hook useEffect has a missing dependency: 'weaponOptions'. Either include it or remove the dependency array react-hooks/exhaustive-deps
The useEffect triggers if the weaponOptions array changes if I pass it as a dependency, resulting in an endless loop because the hook itself changes the weaponOptions state. The same thing happens if I omit the empty array argument.
What is the correct approach here?
weaponOptionscomes from