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

Performance impact: Not re-rendering a component when only calling a shared function #93

Closed
StallionV opened this issue Sep 3, 2019 · 3 comments · Fixed by #97
Closed
Labels
enhancement New feature or request

Comments

@StallionV
Copy link

StallionV commented Sep 3, 2019

Could you elaborate and add an example in the documentation where we can prevent the components from rendering if they are only calling out the functions.

Going with the count and Increment examples.
It is ok to re-render a component which is using count and displaying it if count changes.
But should we really be re-rendering the component which is only calling the increment function. The component calling the function does not care what the new state is, all it is interested is in calling the function.

More examples on these lines would be great, since I could not find more documentation besides the example on the git page.

Great library and idea. This is exactly what I was looking for, ability to create hooks and then share state globally using context !!! I started doing the work and mid way found your library, so much appreciate it.

@StallionV
Copy link
Author

StallionV commented Sep 4, 2019

I also tried referring to the solution you proposed for
#82 (comment)
Which is createMemoInputs

/ /re-render consumers only when value.count changes
const useCounterContext = createUseContext(useCounter, value => [value.count]);

function useCounter() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(count + 1);
  return { count, increment };
}

But here I have another component Like where what I only want is to increment the the counter by 1 automatically every time it loads.
But the below code now load the Like component twice.

function Like() {
  const { increment } = useCounterContext()

  useEffect(() => {
    increment() //We are not using count only calling increment
  }, [])   //You can also use [increment] to avoid warning in console

  return "Like Component"
}

export default Like

The component loads once on the first load and the second due to it being re-rendered since increment was called.
Remove the increment call and it loads only once
This is something that should be avoided, else will be a major perf issue with the library.
Imagine if there are API calls, we don't want same calls going twice.

Please help me understand if I am missing something

@StallionV StallionV changed the title Not re-rendering a component when calling a shared function Performance impact: Not re-rendering a component when only calling a shared function Sep 4, 2019
diegohaz added a commit that referenced this issue Oct 10, 2019
…hanges) (#95)

Renaming `createUseContext` to `createContextHook`. There are no breaking changes, but it deprecates the current usage of the library (importing default).

This will make more sense when we expose more methods (for example, something like `createContextHookArray` that will hopefully address #93).
@diegohaz
Copy link
Owner

diegohaz commented Oct 11, 2019

FYI: I've been working on a solution for this issue. The working in progress is here: https://github.com/diegohaz/constate/tree/feat/multiple-contexts

The API looks like this:

// renamed to createContextHook, but no breaking changes, since it's default export
import createContextHook from "constate";

function useCounter() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(count + 1);
  return { count, increment };
}

const [Provider, useCount, useIncrement] = createContextHook(
  useCounter,
  value => value.count, // becomes useCount
  value => value.increment // becomes useIncrement
);

There are no breaking changes. The current API still works! All these APIs are supported:

const useCounterContext = createContextHook(useCounter);
<useCounterContext.Provider />

const useCounterContext = createContextHook(useCounter, value => [value.count]);
<useCounterContext.Provider />

const [CounterProvider, useCounterContext] = createContextHook(useCounter);
<CounterProvider />
<useCounterContext.Provider />

const [CounterProvider, useCount] = createContextHook(useCounter, value => value.count);
<CounterProvider />

@StallionV
Copy link
Author

I see that you have renamed the API which is a step towards addressing this issue.
Any tentative timelines on it.
I would also recommend adding the example similar to the LIKE one I explained above so that users can make optimized use of this library in the right way and also understand how state variables and functions can be worked with.
Again thanks for getting back, I was just hoping it was being maintained. Your comment today puts me at ease 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants