We have to functions right now. createStore
that creates module state and useStore
that consumes the module state that we created.
The logic is working as expected. State is being properly shared to the components that need it while still isolated from the rest of the app. The issue now is that we have extra re-renders in our application. Each component will rerender when any state changes
To fix this, we'll implement a selector function that will peek the value that you need out of state. This way only the components that depend on the value that is changed will re-render.
Daishi Kato: [0:00] We have created store function to create a store with a module state, and we have used store hook to use the store. They are library code. In application code, we create a store with two properties, count one and count two.
[0:16] There is counter one component to use count one property. The component shows the count number and the button to increment the count number. The inc-one function is to call setState with an updating function. Counter two component is the same component, except that it's for count two property.
[0:37] Finally. we have app component to show two components for each. This works as expected, but there are some extra re-renders. To reveal it naively, let's put must Math.random in the counter components. This is generally not recommended because Math.random is not a pure function. Now, you can see components re-render without updating count numbers.
[1:04] Let's improve our useStore hook to avoid these extra re-renders. We use a selector function, which takes a state value and returns an arbitrary derived value. Typically, selector is used to pick a property of an object. If you don't specify a selector function, it defaults to the identity function. Then, the selector is used right after getting the state.
[1:31] Notice we add the selector to the useEffect dependency array. Now, with the modified useStore hook, we pass a selector function in the Counter1 component. We wrap the selector function with useCallback to make it stable because it's used in the dependency array in useStore. Even if you forget to wrap it, it will still work.
[1:56] The value we get from the useStore hook is now the count1 value instead of the whole state object. Apply the same change in the Counter2 component. It should be ready to check the behavior. If you click the button in the Counter1 area, it doesn't affect the Counter2 area, and vice versa.
[2:20] Let's recap our modification in the useStore hook. It takes a selector function in the second argument and applies it to the state value. When the selector function is changed, it will resubscribe to the store. Re-subscription is very lightweight, but it's usually idiomatic to wrap a selector function with useCallback.