Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Hooks support useCallback and useMemo arguments #286

Closed
evbo opened this issue Jul 24, 2019 · 1 comment
Closed

React Hooks support useCallback and useMemo arguments #286

evbo opened this issue Jul 24, 2019 · 1 comment

Comments

@evbo
Copy link

evbo commented Jul 24, 2019

I've been using Slinky for quite sometime, all the while thinking that per the react.js docs useCallback and useMemo should strictly take () => Unit and () => T as their first argument, respectively.

But towards the bottom of this issue is a valid use-case for when a variable can't easily or conveniently be controlled in state, but must be referenced in the callback that you also might want memoized to avoid re-rendering the child you're passing it to.

Sure enough, if you play around with this code pen, you can write a valid useCallback or useMemo that takes other types, e.g.: useCallback[String](...)

React.withHooks(() => {
  const inputState = React.useState('Hello, world!');
  const onButtonClick = React.useCallback(
    (props) => (
      (e) => {
        const [input] = inputState;
        alert(e);
      }
    ),
    (props) => [inputState[0]]
  );
  return (props) => {
    const [input, setInput] = inputState;
    return (
      <>
        <input value={input} onChange={(e) => setInput(e.currentTarget.value)} />
        <button onClick={onButtonClick('data I need to send not controlled in state')}>Alert</button>
      </>
    );
  };
})

Can Slinky hooks support the following instead? In these cases, the extra type is for an argument that isn't controlled in any state that would otherwise be watched as a dependency:

@inline def useCallback[T](callback: T => Unit, watchedObjects: Iterable[Any]): T => Unit = {
    ...
}

@inline def useMemo[A,T](memoValue: A => T, watchedObjects: Iterable[Any]): T = {
    ...
}

and would get used like:

val someCallback = useCallback[String](
  (dataINeedNotStoreInState: String) => { println(dataINeedNotStoreInState + stateData) },
  watchedObjects = Seq(stateData)
)

Note that there is a work around, albeit forcing the reducer design pattern, which isn't always preferred by matter of coding convention:

So instead of trying to implement:

val func = useCallback[String]((e: String) => {setState(someState + e)} )

You can just do the following for now:

val (someState, func) = useReducer[String, String](
    reducer = (current: String, newChange: String) => {current + newChange}, 
    initialState = ""
)
@shadaj
Copy link
Owner

shadaj commented Aug 6, 2019

In the case of useMemo, Slinky doesn't actually need a new API since A => T can just be the type that the existing T is inferred to be. I'll take a look at useCallback, that's not something that Slinky handles right now.

@shadaj shadaj added this to the v0.6.3 milestone Aug 6, 2019
@shadaj shadaj closed this as completed in 0c0f4fa Aug 17, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants