# Why so many rerenders?

**URL:** https://discourse.threejs.org/t/why-so-many-rerenders/53860
**Category:** Questions
**Tags:** r3f
**Created:** [July 13, 2023, 2:03pm UTC](https://discourse.threejs.org/t/why-so-many-rerenders/53860 "2023-07-13T14:03:55Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![kalabedo](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/kalabedo/32/43091_2.png) [@kalabedo](https://discourse.threejs.org/u/kalabedo)
#### Post date: [July 13, 2023, 2:03pm UTC](https://discourse.threejs.org/t/why-so-many-rerenders/53860/1 "2023-07-13T14:03:55Z")

</div>

Hi,

I’m building a Configurator in R3F, with alot of options to customize. Currently i’m using a custom hook to share the states across my Components (Custumization.jsx, I cut some code for readability) :

```javascript
export const CustomizationProvider = (props) => {
    const [OFL_TB, setOFL_TB] = useState("CPL quer Vivo Choco"); // material bandseitig
    const [OFL_TB_BGS, setOFL_TB_BGS] = useState("CPL quer Vivo Choco"); // material bandgegenseite
    const [OFL_ZA, setOFL_ZA] = useState("CPL quer Vivo Choco"); //zarge material
    [...]

    return (
      <CustomizationContext.Provider 
      value={{
          OFL_TB,
          setOFL_TB,
          OFL_TB_BGS,
          setOFL_TB_BGS,
          OFL_ZA,
          setOFL_ZA,
          [...]
      }}
      >
        {props.children}
      </CustomizationContext.Provider>
    );
  };
  
  export const useCustomization = () => {
    const context = useContext(CustomizationContext);
    return context;
  };

```

I’m wrapping my App.jsx in this cutom hook, so i get access to all states from everywhere. When I’m logging “rerender” in one of the components of my Experience.jsx (it’s in the App.jsx) and i refresh the page i get 13 logs (Image below). I guess the problem is the custom hook but how can I get access to the states in a more efficient way?  
Every tip would be helpful. Thanks

 ![Screenshot 2023-07-13 155401](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/2/d/2d6a52317e6a608348349b8f91e490e37c976ac9.png)

---

<div class="post-metadata">

### Author: ![mjurczyk](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mjurczyk/32/10995_2.png) [@mjurczyk](https://discourse.threejs.org/u/mjurczyk)
#### Post date: [July 13, 2023, 2:41pm UTC](https://discourse.threejs.org/t/why-so-many-rerenders/53860/2 "2023-07-13T14:41:17Z")

</div>

[Zustand](https://github.com/pmndrs/zustand) may be what you’re looking for - it’s a bit more flexible and granular than default React contexts.

---

<div class="post-metadata">

### Author: ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)
#### Post date: [July 13, 2023, 3:40pm UTC](https://discourse.threejs.org/t/why-so-many-rerenders/53860/3 "2023-07-13T15:40:33Z")

</div>

re-render in react isn’t harmful per-se, all it does is check for updates. but the reason is, like @mjurczyk said, context. it isn’t really meant to hold app state, it re-renders all context listeners and their sub trees on every change, which isn’t optimal.

worse, every time CustomizationProvider executes it triggers a fresh re-render of everything listening to CustomizationContext because you didn’t memoize the context value, which i would consider a bug. context shouldn’t be used w/o memoization.

```jsx
   const value = useMemo(() => ({
     OFL_TB,
     setOFL_TB,
     OFL_TB_BGS,
     setOFL_TB_BGS,
     OFL_ZA,
     setOFL_ZA,
   }), [conditions])
   return (
     <CustomizationContext.Provider value={value}>

```

---

<div class="post-metadata">

### Author: ![makc3d](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/makc3d/32/10452_2.png) [@makc3d](https://discourse.threejs.org/u/makc3d)
#### Post date: [July 13, 2023, 3:42pm UTC](https://discourse.threejs.org/t/why-so-many-rerenders/53860/4 "2023-07-13T15:42:45Z")

</div>

however, if his log is in a single component that is used once, and the context is changed once, should we not still get 1 log? I mean, of course, unless he actually calls all 13 of those setXXX methods

---

<div class="post-metadata">

### Author: ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)
#### Post date: [July 13, 2023, 3:44pm UTC](https://discourse.threejs.org/t/why-so-many-rerenders/53860/5 "2023-07-13T15:44:28Z")

</div>

yep, there’s definitively something over triggering it. in strict dev mode the component tree has to render twice because react stresses it out on purpose to flush out bugs and race conditions.

---

<div class="post-metadata">

### Author: ![kalabedo](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/kalabedo/32/43091_2.png) [@kalabedo](https://discourse.threejs.org/u/kalabedo)
#### Post date: [July 14, 2023, 5:05am UTC](https://discourse.threejs.org/t/why-so-many-rerenders/53860/6 "2023-07-14T05:05:31Z")

</div>

Hello, thanks for the replies, i tried it with Zustand and the same happens so here is more code for explanation, thats the Licht Component:

```javascript
export function Licht() {
  const { lichtZustand} = useCustomization();

  return (
    <>
      {/* SpotLight BGS */}
      <spotLight
        ref={spotLight}
        visible={!lichtZustand}
        position={[-2.5, 1.5, -1.5]}
        intensity={20}
        shadow-mapSize-width={4096}
        shadow-mapSize-height={4096}
        color={colorSpot}
        angle={angleSpot}
        distance={7}
        decay={decay}
        penumbra={penumbra}
        shadow-normalBias={0.02}
        target={targetObject}
        castShadow
      />

      <directionalLight
        shadow-mapSize-width={2048}
        shadow-mapSize-height={2048}
        position={[3, 4, 3]}
        ref={directionalLight}
        intensity={intensity}
        castShadow
        shadow-camera-far={10}
        shadow-normalBias={normalBias}
        color={color}
      />
    </>
  );
}

```

The Licht Component is in the Experience.jsx:

```javascript
export const Experience = () => {
  const {
    sceneVisibility,
    wandFarbe,
    MOD_ZA,
    FALZ_MASS,
    BR_TB,
    HOE_TB,
    TB_STAERKE,
    ANR,
    LA,
    BR_ZFM,
    HOE_ZFM,
    FALZ_ZA_TIEF,
    TIEF_ZA,
    AFLG,
    BEKL_BR,
    KA_PROFIL,
    HOE_WAND,
    setLichtZustand,
    lichtZustand
  } = useCustomization();

  return (
    <>

      {/* PERFORMANCE MONITOR */}
      <Perf position="top-left" />

      {/* Kamera Kontrolle implementiert mit OrbitControls */}
      <CameraControls HOE_TB={HOE_TB} BR_TB={BR_TB}/>

      <Environment
        files={"./HDRI/cayley_interior_1k.hdr"}
        intensity={1}
        resolution={1024}
      />

      <Türelement
        HOE_TB={HOE_TB}
        BR_TB={BR_TB}
        TB_STAERKE={TB_STAERKE}
        KAUS={KA_PROFIL === "STUMPF" ? false : true}
        FALZ_MASS={FALZ_MASS}
        KA_PROFIL={KA_PROFIL}
        ANR={ANR}
        MOD_ZA={MOD_ZA}
        LA={LA}
        FALZ_ZA_TIEF={FALZ_ZA_TIEF}
        HOE_ZFM={HOE_ZFM}
        BR_ZFM={BR_ZFM}
        TIEF_ZA={TIEF_ZA}
        AFLG={AFLG}
        BEKL_BR={BEKL_BR}
      />

      <WandNeu 
        FALZ_MASS={FALZ_MASS}
        WAND_FA={wandFarbe}
        HOE_TB={HOE_TB}
        BR_TB={BR_TB}
        TIEF_ZA={TIEF_ZA}
        KAUS={KA_PROFIL === "STUMPF" ? false : true}
        HOE_WAND={HOE_WAND}
        setLichtZustand={setLichtZustand}
        lichtZustand={lichtZustand}
      />

      <Licht />

    </>
  );
};

```

Is the problem, that the Experience uses so many states? And the initializing of those states triggers one rerender of the Experience? If yes, how can i make sure this does not happen (using default values maybe)?

---

<div class="post-metadata">

### Author: ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)
#### Post date: [July 14, 2023, 7:39am UTC](https://discourse.threejs.org/t/why-so-many-rerenders/53860/7 "2023-07-14T07:39:12Z")

</div>

Zustand can pick state, the point of it is that components can listen and react only to state they use and everything else stays put. But if you use it the same way as context, one major glob and every change triggers it and then you distribute it via prop drilling, that wouldn’t make sense.

Using it is good, but move state access to the components that rely on state

```
function Foo() {
  const foo = useStore(state => state.foo)
  const bar = useStore(state => state.bar)

```

That component listens to foo and bar, will only render it either of these changes unless it gets triggered by a parent rendering.

In your app there’s a part that triggers a state update 13 times, so you end up on the parent component 13 times. You have to figure out which does that.
