is it possible to use a function
as my React Component's state ?
example code here:
// typescript type OoopsFunction = () => void; export function App() { const [ooops, setOoops] = React.useState<OoopsFunction>( () => console.log('default ooops') ); return ( <div> <div onClick={ ooops }> Show Ooops </div> <div onClick={() => { setOoops(() => console.log('other ooops')) }}> change oops </div> </div> ) }
but it doesn't works ... the defaultOoops
will be invoked at very beginning, and when clicking change oops
, the otrher ooops
will be logged to console immediately not logging after clicking Show Ooops
again.
why ?
is it possible for me to use a function as my component's state ?
or else React has its special ways to process such the function state
?
The () => { ... } is the function. It's an ES6-style "arrow" function expression. These are like function expressions ( tick = function() { ... } ) except that the this value within the function is inherited from the context in which it's defined rather than being set when the function is called.
useState is a Hook (function) that allows you to have state variables in functional components. You pass the initial state to this function and it returns a variable with the current state value (not necessarily the initial state) and another function to update this value.
The React useState Hook allows us to track state in a function component. State generally refers to data or properties that need to be tracking in an application.
React components can possess internal “state,” a set of key-value pairs which belong to the component. When the state changes, React re-renders the component. Historically, state could only be used in class components. Using hooks, you can apply state to functional components too.
It is possible to set a function in state using hooks, but because state can be initialized and updated with a function that returns the initial state or the updated state, you need to supply a function that in turn returns the function you want to put in state.
const { useState } = React; function App() { const [ooops, setOoops] = useState(() => () => console.log("default ooops")); return ( <div> <button onClick={ooops}>Show Ooops</button> <button onClick={() => { setOoops(() => () => console.log("other ooops")); }} > change oops </button> </div> ); } ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div>
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);
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:
React.useState(0)
- initial value 0
),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.
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.
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.
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