Some of the React.
Tags: react, webdev
Published: 2022-05-10 05:19:02

Here are the some of the concepts and practices that I learnt while making my projects.

 1. [Batching](#batching)
 2. [Reconciliation](#reconciliation)
 3. [Composition](#composition)
 4. [React Router v6](#router)
 5. [CSS Modules](#cssmodules)
 6. [useRef Hook](#useref)

### Batching in React.<a name='batching'></a>

When I started using `useState`, I had a misconception that the component is rendered as soon as the `setState` statement is encountered. I realized this later that React does not render right after the `setState` statement. Any state update operations are batched together and queued to be computed when the `useState` is invoked during the next render. The component renders only when the event handler function has executed all the code that it had. Then, during the next render, those state updates that were batched are computed and the value is returned to the state variable. Thus, when the component renders and the hooks are invoked, they return the updated value to the state. Here is an example,

```JS
export default function App() {
  const [a, setA] = useState(1);

  const handleBtnClick = () => {
    setA(a + 1);
    setA(a + 1);
    setA(a + 1);
    setA(a + 1);
  };

  console.log("rendered", a);

  return (
    <div className="App">
      <button onClick={handleBtnClick}>do it</button>
    </div>
  );
}
```
If you run this, you will see that the `console.log` will run only once and give the value `2`. If you have used `React.StrictMode` you might get the same output twice. Now, this example brings me to the next point which is the updater function.

In this example, since we are providing an operation inside `setA`, the `setA` is converted to `setA(1+1)` which is converted to `setA(2)` and then these updates are queued for the next render. Then, during the next render, `useState` has four state updates and all of them are `setA(2)`. Why 2 for all of them? That is because every render has it's own state value and this state value does not change for that particular render. You might have noticed that in the line where `useState(1)` is invoked and we are de-structuring the array into the state value and state update function, we have used `const`. This means that we cannot change the state value during the same render. The previous render had the value of `1` for `a`. Therefore, all the `setA` statements were read as `setA(2)`. The final value that is returned to the component is `2`.

In case of a scenario where we want to serially update the state unlike the scenario mentioned above where the state was only replaced by the same constant value of `2` on every update, we would use an updater function.

An updater function is a callback function that is supplied to the `setA`. It's argument is the latest state value prior to this calculation. Here is an example,

```JS
const handleBtnClick = () => {
    setA((a) => a + 1); // this returns 2
    setA((a) => a + 1); // this returns 3
    setA((a) => a + 1); // this returns 4
    setA((a) => a + 1); // this returns 5
  };
```
By giving a callback function, we are telling React to calculate the state value during the next render.

### Reconciliation<a name='reconciliation'></a>

React uses this algorithm to make sure the DOM rendering is as efficient as possible. React has the diffing algorithm through which it narrows down which elements are different so that only those elements are updated in the browser DOM. This process starts with `ReactDOM.render()` method. This `render` method creates a virtual DOM. During diffing, the newly created virtual DOM is compared with the virtual DOM before the state update. But first, a bit about virtual DOM. 

Virtual DOM is a JSON object that represents the browser DOM. It is extremely fast compared to the browser DOM. It is created from scratch on every state update.

How does React compare the corresponding elements from two different virtual DOMs? For that, let me show you this example,

```JSX
console.log(
createElement(
<p className="App">some random text</p>
));
```
This code gives the following output,

![react element](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m8upfypyfzs9cqiv905b.png)

React sees every node like this and then compares their respective properties. For any element to be called different, any of these properties have to differ from the properties of the same element of the previous virtual DOM.

All the child nodes are mentioned in `children` object. React gives warning for having unique keys for child nodes. Whenever React sees a different element, it not only re-creates that element but also all its children. So, having a unique key helps React in determining whether a particular child node is new or updated or removed from the list of children.

In a case without keys, adding a child on top of the list would mean that the whole list is destroyed and re-created. But having a key would tell the React to add the new element to the list instead of destroying the whole list.

One more thing. Think of the whole component tree in terms of a React Elements. The root component would have `children` where the child components would be listed and some of these would have `children` too. Continuing like this you can imagine a tree is forming that starts at the root and the leaf nodes are the HTML elements. This is the component tree that React is traversing during the diffing to spot the differences. To traverse this tree, React uses breadth first approach. To make a case for depth first traversal, let's say during diffing, React sees that a leaf node is different. So it destroys this node and creates it again. Now, it goes to the parent node and sees that this node is also different. It destroys this parent node and it's subtree and re-creates the whole subtree again. The same could have been done in a single operation had there been a breadth first traversal. React would first check the parent node instead of going directly to the child node. 

Once the process of diffing is complete, React prepares a list of minimum updates required to be done on the browser DOM.

### Composition<a name='composition'></a>

React uses the idea of function composition from JS. Components can be composed in a similar manner. Higher order component is one such function that takes the child component as an argument and returns this component wrapped in the parent component. What component is passed as an argument will change depending on the use case. Here is an example,

```JSX
const FeedPageWrapper = PostsSection => {

    const FeedPage = () => {

        return (
            <div
                className={`bg-off-secondary ${styles.feedPageGrid}`}>
                <div className={`${styles.navDiv} flx flx-maj-end`}>
                    <NavBar />
                </div>
                <PostsSection /> {/*child component used here*/} 
                <div className={styles.extraDiv}>
                    {/* third div empty for now.*/}
                </div>
            </div>
        )
    }
    return FeedPage
}

export default FeedPageWrapper
```
In the above example, I have a higher order component that takes a component called `PostsSection`. This component that is passed as an argument will differ based on the page that the user is on. If the user is on bookmarks page, `PostsSection` will have a list of bookmarked posts. If the user is on user-feed page, `PostsSection` will have a list of posts personalized for the user. 

Apart from the `PostsSection`, everything else on the page will be the same. Hence, I decided to use the higher order component here. Here is how this component will be used,

```JS
const BookmarksFeedPage = FeedPageWrapper(BookmarksSection)

export default BookmarksFeedPage
```
I have passed `BookmarksSection` as the argument and `BookmarksFeedPage` is returned that is exported in the next line. Similarly for the user-feed page,

```JS
const UserFeedPage = FeedPageWrapper(UserFeedSection)

export default UserFeedPage
```


### Private routes using react router<a name='router'></a>

By private routes I mean the routes that are personalized for the users and should only be shown if a user is logged in. For example, in an e-commerce app, wish-list and cart pages are the private routes because they will have different data for different users, unlike the products page.

Here is the algorithm,
 1. Check if the current route is private or not.
 2. If it is, then check whether the user is logged 
    in or not.
 3. If user is logged in, let the user continue 
    with this route.
 4. If user is not logged in, re-direct the user 
    to the login page.
 5. If the current route is not private, then let 
    the user continue with this route.
&nbsp;

```JSX
<Route path={ROUTE_CART} element={
          <RequireAuth>
            <Cart />
          </RequireAuth>
} />
```
In the above code, I have wrapped `<Cart/>` inside `<RequireAuth/>` which checks whether the user is logged in or not.
&nbsp;

```JSX
const RequireAuth = ({ children }) => {
        const location = useLocation()
        return isUserLoggedIn ? children : <Navigate to='/login' state={{ from: location }} replace />
    }
```
The above code shows that user's log in status is maintained in the state `isUserLoggedIn`. `<Navigate/>`
is a component in react-router@6 which takes a parameter `to` to navigate to a particular location.
The user's current location is also saved inside the state of `Navigate` so that after log in, user can be redirected to this location. Here is the code for that,
&nbsp;

```JS
const from = location.state?.from?.pathname
navigate(from, { replace: true })
```
Setting replace to true means that the login page would be removed from the history stack of the browser. This is helpful when the user presses the back button, the app skips the login page and goes to page that was opened previous to the login page.

### CSS Modules<a name='cssmodules'></a>

Initially I had used normal CSS stylesheets in my projects. This was raising specificity conflicts because every stylesheet had a global scope. CSS modules resolved this issue because it limits the scope of stylesheet to the file that it is imported in. 

### useRef <a name='useref'></a>

I have used useRef in one of my apps to make DOM manipulations. The requirement was that whenever a user clicks on any option from the given options, the app should change the background color of that option to red or green depending upon whether the answer was correct or wrong. Here is the first part of logic,
&nbsp;

```JS
optionBtnRefs.current = currentQues?.options?.map((option, i) => optionBtnRefs[i] ?? createRef())
```
This code is creating an array of refs for each option of the question. Then,
&nbsp;

```JSX
<button key={index} ref={optionBtnRefs.current[index]} onClick={() => handleOptionSelect(optionBtnRefs.current[index])} value={option}>{option}</button>
```
When mapping over the options, I have assigned a ref to each option and the same ref is passed to `onClick` event handler. Then,
&nbsp;

```JS
if (ref.current.value === currentQues.answer) {
            ref.current.style.background = 'var(--clr-success)'
            setTimeout(() => { ref.current.style.background = 'var(--clr-primary)'; setScore(s => s + 1) }, 1000)

        } else {
            ref.current.style.background = 'var(--clr-error)'
            setTimeout(() => ref.current.style.background = 'var(--clr-primary)', 1000)
        }
```
Depending upon whether the chosen option is the correct answer or not, I have updated the background of that particular `ref`. The background is restored to normal after 1 second. 

These were some of the things I wanted to share. Hope it helps. Thanks for reading.