In my React TS component I have a bunch of fields, contrived example below, that check a specific condition, and if it is not met, set the specific field error to true, to be reflected and the component DOM (and thus not submit) However when I have the code below it throws an expression not callable on the setErr function.
const App = () => {
const [name, setName] = React.useState("");
const [email, setEmail] = React.useState("");
const [nameError, setNameError] = React.useState(false);
const [emailError, setEmailError] = React.useState(false);
return (
<div className="App">
<input
type="text"
value={name}
style={{
border: `1 px solid ${nameError ? "red" : "black"}`
}}
onChange={e => {
setName(e.target.value);
}}
/>
<input
type="text"
value={email}
onChange={e => {
setEmail(e.target.value);
}}
style={{
border: `1 px solid ${emailError ? "red" : "black"}`
}}
/>
<button
onClick={() => {
const errors = [
[setNameError, name.length],
[setEmailError, email.length]
];
let canSubmit = true;
errors.forEach(validation => {
const [setErr, condition] = validation;
console.log(!condition);
if (!condition) {
canSubmit = false;
setErr(true); // <---- ERROR HERE
}
});
if (canSubmit) { /* submit the form */ }
}}
>
submit
</button>
</div>
);
};
This only errors in TypeScript as it works fine in vanilla/jsx. And doesn't compile in some build systems.
Full error is:
This expression is not callable.
Not all constituents of type 'string | number | boolean | Dispatch<SetStateAction<boolean>>' are callable.
Type 'string' has no call signatures.
I am especially confused why it thinks setErr is of type string, when it should be equal to the setNameError function destructured from useState.
All you need is to add as const to the errors declaration:
const errors = [
[setNameError, name.length],
[setEmailError, email.length]
] as const;
That way, the arrays won't be typed as arrays but as tuples.
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