React.js Signals: A Comprehensive Guide

Sudip Paudel July 24, 2024

In this blog we are going to learn how to set up the signal and use it to manage the state in react without re-rendering the component. As we know, if we want to pass the data from one component to another component we would probably pass it by using the method called props drilling.

How to overcome the prop drillings?

Prop drilling is basically a situation when the same data is being sent at almost every level of a child component which increases the code complexity, difficult to maintain the code, performance overhead, increases the development time and many more. To overcome these problems, react has introduced a state management library like redux or react context API which adds a lot of complexity in the small to medium-sized applications.

In this situation, another simple and elegant solution to the problem of managing the state in react is Signal which can be used to share the data between components. The most important thing is that when the signal changes, it updates the UI without re-rendering the whole component. Signals are not bound with the components. React provides a library called @preact/signals-react for using the signals.

Installation and Usage for @preact/signals-react

  1. Prerequisites
    It is very important to Install Node.js and npm before installing signal.

  2. Install @preact/signals-react
    Run the following command to install @preact/signals-react:
    npm install @preact/signals-react

  3. Using Signals
    1. Define signal
      Since signals are not bound to the component, we can define a signal outside the component and use it inside the component. This is useful when we want to share the signal between multiple components. Let's define a signal outside the component in a separate file signals/app.tsx
      
      -> signals/app.tsx 
      import { signal } from "@preact/signals-react";
      export const count = signal(0);
      

    2. Use the signal in Component
      
      import React from 'react';
      import { count } from "signals/app";
      
      export default function Parent() {
      console.log(“rendered?”)
       return(
         <>
           

      Count: {count}

      <button onClick={() => count.value += 1}>Increment</button> <button onClick={() => count.value -= 1}>Decrement</button> </> ) }

      Now we can import the count to Increment or Decrement the value of count in the Parent component. When we press the button increment or decrement we can see that the value of count is changed but the text in console.log i.e rendering is never printed in console because the components are not re-rendered using the signals but the values are changed.

      Let's take an example where we want to share the value of count between multiple components. Let's make another component called Child.

      
      import React from 'react';
      import { count } from "signals/app";
      
      export default function Child() {
      console.log(“rendered?”)
       return(
         <>
           

      Count: {count}

      <button onClick={() => count.value += 1}>Increment</button> <button onClick={() => count.value -= 1}>Decrement</button> </> )

      Let's say we increment the value of count to 10 in the Parent component. If we navigate to the Child component the value of count will still be 10 and if we increment or decrement the value of count in the Child component then it starts incrementing/decrementing from 10 and not from 0 which means the values are shared in the Child component as well.

Why use Signals?

  1. Simplicity and Ease of Use
    Unlike Redux and Context, signals do not have a complex setup. Signals provide a straightforward API that simplifies state management.

  2. Performance
    Signals update the components when signal changes and updates the UI without re-rendering the whole component.

  3. Lightweight
    Signals are lightweight and add minimal overhead to the application, making them a good choice for projects where performance and bundle size are important.

Conclusion

Despite its simplicity, performance and lightweight, they are only used for simple to medium-sized applications which offer a highly efficient and friendly state management solution. Choosing to use signals in the React application depends on the specific needs and project complexity. For larger, more complex applications, traditional state management libraries like Redux would be the better choice.

Ps. if you have any questions

Ask here