DEV Community

Awa
Awa

Posted on

10 'Aha' Moments: Navigating React's Doc!

Since the React documentation update, I hadn't found the time to thoroughly go through it. In the past two days, I dedicated myself to sifting through every detail, looking for any previous misunderstandings and gaining new insights. So, Here, I share the 10 misconceptions I had about React!



1. React Assumes Every Component is a Pure Function

Purity in programming is a way of writing functions. There are many programming paradigms (paradigm means the rules or structures for writing your app). There are two common paradigms: OOP and Functional Programming. In the past, React was implemented in OOP, therefore, there were classes. However, later they switched to Functional Programming, where the concept of purity is highly important. What it stands for is simple: a pure function is a function that contains all it needs inside it without relying on external values. For example:

function addNumbers(a, b) {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

Notice how the function takes two arguments and returns them without relying on anything other than them. And notice here:

let total = 0;

function addToTotal(number) {
  total += number;
  return total;
}
Enter fullscreen mode Exit fullscreen mode

how the function is impure and relies on external resources to compute the value. React is fundamentally designed around this concept, therefore, as the heading says: React assumes that every component you write is a pure function.



2. React's Re-rendering Process is Recursive

It may be a bit strange to be surprised about such a thing, but I hadn’t really thought about it, although it makes sense. Recursion in programming is a way of solving specific types of problems, which are recursive problems. A recursive problem is a problem where the initial returned value of a function needs to be computed n times in order to produce the final value. In a nutshell, a function calls itself multiple times until it reaches its final condition. So in React, when you're mounting a component, it checks if there are other components inside it that need to be mounted and checks inside them again and again until it renders them all.



3. Think of React States as Snapshots!

Start to think about React States as snapshots! This one is so cool! I always thought about states in a formless way, like a box or a variable, however, thinking about them as snapshots solidifies their functionality even more. Unlike regular JavaScript variables, React state behaves more like a snapshot. So setting it does not change the state variable you already have, but instead triggers a re-render with the new “value” or snapshot!



4. Every Render Has its Own DNA

In every re-render, a component's internal variables and event handlers don’t “survive” re-renders. Instead, they get recreated, so every render has its own event handlers!



5. Paradoxical and Impossible States

When working with states, try to visualize your component logic before implementing it, because as long as you make your states concise and few, you'll maintain conciseness and avoid bugs. As the Docs say:

“Remove any non-essential states.”

Creating many states can result in common logical errors between them, where one state paradoxically contradicts others. For example, imagine a checkbox component that can be either checked or unchecked. If the component's state somehow indicates that it's both checked and unchecked simultaneously, it's in a paradoxical state. Impossible states are states that are theoretically not possible based on the business logic of the application. For example, if you have a form with required fields, it's an impossible state for the form to be submitted without those fields being filled out. If this were to happen, it would indicate a bug or a logic error in the application.



6. Don't Mirror Props

Don't mirror props. If you are passing a state from parent to child, avoid storing the passed prop into a local state. Because if the parent's state gets updated, the local state will override it. Instead, use it directly, and if you find the need to shorten it, consider storing it in a constant variable.



7. Consider Using Immer for Concise, State Updates

Consider using Immer for concise state updates, especially for objects and arrays. Immer is a handy library when working with objects and arrays. Here's how Immer works: In React, it's clearly not recommended to mutate objects and arrays. Instead, it's better to reproduce them with the new value. In other words, copy them to a new state and override them with the desired changes. This can be a bit painful, especially if your state is nested and you don't want to change its structure, i.e., flattening it. So, Immer comes to solve this problem by introducing a very intuitive and convenient way. To update state with Immer, you would mutate it like you are mutating a normal object. And it looks like you are breaking the rules! But it's not, because you are not directly mutating the original state, but instead, you are mutating a proxy state that lets you change it, and then it does all the magic for you under the hood, by comparing the changes to the proxy state to the original and then producing the new one!



8. Preserving and Resetting State

Imagine a parent component with its state passed down to two children. If one child updates it, the other will also re-render since the parent component re-renders due to the state update. However, the internal states of the other child won't be destroyed because they're tied to the component's lifecycle. The lifecycle comprises three stages: Mounting, Re-rendering, and Unmounting. So, internal states are only destroyed when the component gets unmounted. But during re-rendering, the states persist because it's actually a fundamental part of the component's lifecycle.



9. useReducer and useState are Technically the Same

useReducer and useState are technically the same. The main difference between them, or the main reason that may make you choose useReducer over useState, is when you have multiple event handlers in your component that are updating the same state. Instead of having all these sprinkled handlers all over your component, you can abstract them into a single file, and contain them into a single packet, and organize them using if statements or even better, switch cases.



10. useEffect is Meant for External Systems!

The primary purpose of useEffect is to interface with external systems. useEffect is an escape hatch provided by React to let you escape their paradigm. As stated in the doc:

"Effects are an escape hatch from the React paradigm. They let you “step outside” of React and synchronize your components with some external system."

So if one wants to sync anything that's React related, using useEffect would be insufficient! A list of common systems outside of React that you might interact with using tools like useEffect:

  • Browser APIs (DOM manipulation, timers, etc.)
  • Network Requests (HTTP requests to servers, API calls)
  • WebSockets and Server-Sent Events (Real-time communication)
  • Global State Management (Redux, Context API, etc.)
  • Browser Storage (localStorage, sessionStorage)
  • External Libraries and Modules
  • Native Modules (in React Native) (for mobile applications)
  • Event Listeners (e.g., clicks, key presses)
  • Browser History and Navigation
  • Browser Cookies and Headers
  • Geolocation APIs (for accessing user’s location)
  • Media APIs (audio, video, etc.)
  • Canvas and WebGL APIs (for graphics)
  • Device APIs (accessing

Top comments (0)