Imagine a scenario that there's a same operation through different values (For instance generating a custom html element for different input values); in the case of using a component class, I would mocked this as follow:
const onFuncClicked = property => newVal => {
this.setState({ [property]: newVal })
}
but what if i use react hooks:
const onFuncClicked = property => newVal => {
eval(`set${property}(${newVal})`);
}
not only using eval is not recommended for thousands of reasons, but this code does not work at all!! It generates the correct useState function but the component does not know it even and gives a ReferenceError that that function (generated useState) is not defined
To type the useState hook as an array of strings in React, use the hook's generic, e.g. const [names, setNames] = useState<string[]>([]) . The state variable can be initialized to an empty array or an array of strings and will only accept string values. Copied!
The error "React hook 'useState' is called conditionally" occurs when we use the useState hook conditionally or after a condition that may return a value. To solve the error, move all React hooks above any conditionals that may return a value.
Always use Hooks at the top level of your React function. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That's what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.
One way to approach this is to use a map of methods to the property names:
const [property, setProperty] = useState(defaultValue);
const methodMap = { propetryName: setPropertyName, /* ... more fields */ };
Then you can call it from your set method like so:
const onClicked = (property, value) => {
methodMap[property](value);
}
Another option, and probably more common one, would be to have state as an object with all your properties and change them by prop name:
const [state, setState] = useState({property: value});
const onClicked = (property, value) => {
setState(state => {...state, [property]: value});
}
well, if you are already using hooks and useState
and did end up with a bunch of them that make your code look too complex I suggest using useReducer
, here is a sample from official documentation:
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</>
);
}```
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With