TL;DR
Yes, it is possible to use a function as the React Component's state. In order to do this, you must use a function returning your function in React.useState
:
const [ooops, setOoops] = React.useState<OoopsFunction>(
() => () => console.log('default ooops')
);
// or
const yourFunction = () => console.log('default ooops');
const [ooops, setOoops] = React.useState<OoopsFunction>(
() => yourFunction
);
To update your function you also must use a function returning your function:
setOoops(() => () => console.log("other ooops"));
// or
const otherFunction = () => console.log("other ooops");
setOoops(() => otherFunction);
Detailed Answer
Notes about React.useState
The signature of useState
in React with types is
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
It shows, that there are two ways to set the initial value in your state:
- Provide the initial value as is (
React.useState(0)
- initial value 0
),
- Provide a function, which returns the initial value to be set (
React.useState(() => 0)
- initial value also 0
).
Important to note: If you provide a function in React.useState
, then this function is executed, when React.useState
is executed and the returned value is stored as the initial state.
How to actually store functions
The problem here is if you want to store a function as state you can not provide it as initial state as is, because this results in the function being executed and its return value stored as state instead of the function itself. Therefore when you write
const [ooops, setOoops] = React.useState<OoopsFunction>(
() => console.log('default ooops')
);
'default ooops'
is logged immediately when React.useState
is called and the return value (in this case undefined
) is stored.
This can be avoided by providing a higher order function returning your function you want to store:
const [ooops, setOoops] = React.useState<OoopsFunction>(
() => () => console.log('default ooops')
);
This way the outer function will be definitely executed when first running React.useState
and its return value will be stored. Since this return value is now your required function, this function will be stored.
Notes about the state setter function
The state setter function's (here setOoops
) signature is given as
Dispatch<SetStateAction<S>>
with
type Dispatch<A> = (value: A) => void;
type SetStateAction<S> = S | ((prevState: S) => S);
Like in React.useState
there is also the possibility to update state with a value or a function returning the value. So in order to update state the higher order function from above has to be used as well.
prevState
. I also found this article helpful: medium.com/swlh/… – Kincardine