I am trying to store a simple callback in the React context that is set by one component and then called by another component, to facilitate communication between them. This is because the two components do not have any child-parent relationship and are in distinct subtrees of the app. And, I want to assign a custom event handler from Component1 to the click behavior of Component2.
Accordingly, I created the context with a function (the callback) and its setter
import { createContext, useContext, useState } from "react"
interface ContextShape {
myCallback?: (searchInput: string) => void
setMyCallback: (onSearchCallback: (searchInput: string) => void) => void
}
const MyContext = createContext<ContextShape>({
myCallback: () => {},
setMyCallback: () => {},
})
export const useMyContext = () => useContext(MyContext)
export const MyContextProvider: React.FC = (props) => {
const [myCallback, setMyCallback] = useState<(searchInput: string) => void>(() => {})
return (
<MyContext.Provider
value={{
myCallback: myCallback,
setMyCallback: (clientCallback) => {
setMyCallback(clientCallback)
},
}}
>
{props.children}
</MyContext.Provider>
)
}
The component where the click event originates, calls the callback like so:
const { myCallback } = useMyContext()
const handleKeyPress = (
e: React.KeyboardEvent<HTMLInputElement>,
sVal: string | undefined
) => {
if (e.code === "Enter" && myCallback) {
myCallback(sVal || "")
}
}
And, I am trying to set the callback like so, from a page in my app:
useEffect(() => {
// eslint-disable-next-line no-console
setMyCallback(() => (text: string) => console.log("Hii" + text))
}, [])
Notice something weird? While setting the callback, I have to wrap it in another function (() => {... my callback...}). Only then, does this behave as expected. If I pass the callback directly, then it is immediately called instead of being stored and called later. (I checked extensively for whether it is being called mistakenly somewhere, but nowhere does the code do myCallback() unintentionally). This is something that is unexpected for me, as I expect that just (text: string) => {...} is enough for a callback and does not denote that I want to call the function immediately.