React - Don't update parent state in the rendering phase of the child
Tags: react, hook, state, effect
Published: 2022-01-19 17:14:00

TLDR;
**Don't update parent state in the rendering phase of the child component**
<hr>

## Long story

Visualize in your mind this Abstract React tree:

```jsx
<WebSite>
  
  <LoadingSpinner />
  
  <PageContent>
    <A>
      <ASub>
        <ASubSub>
          <LoadingTriggerA />
        </ASubSub>
      </ASub>
    </A>
    <B>
      <BSub>
        <BSubSub>
          <LoadingTriggerB />
        </BSubSub>
      </BSub>
    </B>
  </PageContent>

</WebSite>

```
The goal is to render a single LoadingSpinner in our whole website, and being able to trigger the LoadingSpinner visibility from `LoadingTriggerA` and `LoadingTriggerB` when they need to.

How to solve this without passing functions down the tree - aka “prop drilling“ ?

React Context, using a "useAppLoading" custom hook.

This custom hook takes care of maintaining the visibility state of the Loading component, and to render it.
This hook exposes us a `show` and a `hide` function.

In this post we are focused not on the custom hook, but here you can find the code for build a ["useAppLoading" custom hook](https://magz.techover.io/2020/03/01/loading-indicator-with-react-context-api-hooks/).

```jsx
import { AppLoadingProvider, useAppLoading } from './my-custom-hook/useAppLoading';

const Website  = () => {
  return (
    <AppLoadingProvider>
      <PageContent  /> // LoadingTriggerA and LoadingTriggerB are descendants of this
    </AppLoadingProvider>
    );
};

const LoadingTriggerA = () => {
   const {showLoading, hideLoading} = useAppLoading();
   ...
   return <div>....</div>;
}
 
const LoadingTriggerB = () => {
   const {showLoading, hideLoading} = useAppLoading();
   ...
   return <div>....</div>;
}
```


It seams ok.
But how do we call "show()" and "hide()" functions ???
This is **THE POINT** of this post.


Maybe like this ??

```jsx
const LoadingTriggerA = () => {
   const {showLoading, hideLoading} = useAppLoading();
   showLoading();
   return <div>....</div>;
}
 
const LoadingTriggerB = () => {
   const {showLoading, hideLoading} = useAppLoading();
   hideLoading();
   return <div>....</div>;
}
```

Try yourself and you will notice that React javascript console triggers an error in the console saying:

```plain
Warning:
Cannot update a component (`AppLoadingProvider`) while rendering a different component (`LoadingTriggerA`).
To locate the bad setState() call inside `LoadingTriggerA`,
follow the stack trace as described in https://reactjs.org/link/setstate-in-render
```

What this means is that, child component can't update one of his parents component's state from within the rendering body.
That's what this warning is telling you.

This is an Anti Pattern because if it was legal, there will be chances that data flow going crazy, and weird stuff will happen, like unnecessary re rendering  of the tree.

In our case the Parent is the AppLoadingProvider, which treat LoadingTriggerA and LoadingTriggerB as descendants.

So How to solve that ??

Update the (parent) state inside an useEffect, because useEffect runs after the main rendering phase of a component.

```jsx
const LoadingTriggerA = () => {
   const [busy, setBusy] = React.useState(false);
   const {showLoading, hideLoading} = useAppLoading();

   React.useEffect(() => {
     if (busy) showLoading();
     else hideLoading();
   }, [busy]);

   return <div>....</div>;
}

```

Thank you for reading this blog post.
Not clear ? Question ? Ask in comments !!