I'm trying to use useState with a void returning lambda. For example (TypeScript):
const [doSomething, setDoSomething] = useState<() => void>();
What I'm finding is that when I call setDoSomething, not only does it set the state to the lambda I've defined, but it also invokes the lambda. For example (TypeScript):
setDoSomething(() => alert("Did something!"));
This statement results in an alert showing "Did something!" I just want to set the state to a lambda at this point, I don't want to invoke it. I want to invoke it later by doing:
doSomething();
I think maybe what's going on is that React.js is treating my lambda as a lambda to lazily get the state value, but this is not the desirable behavior in this case. Is it possible to use useState with lambda types?
React DOES treat lambda the way you think. You can create a custom hook with useReducer to get around that limitation.
const useState2 = initVal => {
const setter = useRef((__, next) => ({ val: next })).current
const [wrapper, dispatch] = useReducer(setter, { val: initVal })
const state = wrapper.val
const setState = dispatch
return [state, setState]
}
Live Demo:
const { useRef, useReducer } = React
const useState2 = initVal => {
const setter = useRef((__, next) => ({ val: next })).current
const [wrapper, dispatch] = useReducer(setter, { val: initVal })
const state = wrapper.val
const setState = dispatch
return [state, setState]
}
function App() {
const [say, setSay] = useState2(() => console.log('something'))
return (
<div>
<button onClick={say}>say something</button>
<button onClick={() => setSay(() => console.log('yo!'))}>say yo! instead</button>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('app'))
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Another simpler work-around would be to wrap your lambda in another lambda:
setDoSomething(() => () => alert("Did something!"));
The outer lamba is invoked by React, the inner lambda is invoked by you.
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