4

I am new to web development and was trying my luck with React.js.

I started exploring the Context API where I realised that re-renders (if mounted)/update happens when a component is subscribed to a context and the value of the context is changed.

So I tried understanding the situation by writing some snippets, here is the full code-base.

In the example, I created two components (BucketVegies.jsx and BucketFruits.jsx) with a common parent (Fridge.jsx)

Then I created two context, ContextVegies and ContextFruits with their own providers and consumers. I exposed the consumers using custom hooks (useVegiesContext and useFruitsContext)

My Question is:

Why are sibling components re-rendering upon changing the values in either of the context? From what I read, only the component subscribed to a context must re-render/update when only its context values is changed. (In our example we "add" an item on button click hence change of value)

odus-ex
  • 93
  • 1
  • 7
  • 1
    Tried using `react-memo` or similar? Got answer? I tried separating the provider to sibling. Doesn't work. – tanmoy Aug 27 '21 at 20:01
  • I did not pursue it further as it was more of an optimisation activity, but would love any suggestions. – odus-ex Aug 29 '21 at 07:58

1 Answers1

0
 const handleAddFruits = useCallback(() => {
    setFruits(fruits=>[...fruits, `Fruit${fruits.length + 1}`]);
  },[]);
  const handleAddVegies = useCallback(() => {
    setVegies(vegies=>[...vegies, `Vegie${vegies.length + 1}`]);
  },[]);
const vegiesValue=useMemo(()=>({ vegies, handleAddVegies }),[vegies,handleAddVegies])
const fruitsValue=useMemo(()=>({ fruits, handleAddFruits }),[fruits,handleAddFruits])
  return (
    <ContextVegies.Provider value={vegiesValue}>
      <ContextFruits.Provider value={fruitsValue}>
        {children}
      </ContextFruits.Provider>
    </ContextVegies.Provider>

This solved the issue in the FridgeContext.

If you want to try this library, react-context-slices, it makes working with context fast and easy. You can do it like this with this library:

// slices.js
import getHookAndProviderFromSlices from "react-context-slices"
export const {useSlice, Provider} = getHookAndProviderFromSlices({
  count: {initialArg: 0},
  // rest of slices of Context you want to define
})
// app.js
import {useSlice} from "./slices"
const App = () => {
  const [count, useCount] = useSlice("count")
  return <>
    <button onClick={() => setCount(c => c + 1)}>+</button>{count}
  </>
}
roggc
  • 3
  • 4