Managing State With Signal
Tags: webdev, react, signal
Published: 2022-12-23 02:46:50

by [Deborah Emeni](https://blog.openreplay.com/authors/deborah-emeni)

In this modern era, frontend web applications do not only persist data across components but also handle updates and perform necessary actions. This is where **State Management** comes in. State management is the process of maintaining data integrity across multiple related data flows that comprise a complete session and managing the application's current state.

**State** refers to the condition of an application based on its stored inputs, which are saved as variables or constants. State management enables developers to determine the state of an application to ensure that changes made accurately reflect the real-world context and business processes. You can use the [**Signal**](https://preactjs.com/blog/introducing-signals/) tool to manage states more efficiently.

This article demonstrates what Signal is and how it works. You'll learn how to use it to manage the state in a Preact application.

To follow along with this tutorial, you'll need the following:

- A code editor ([VS Code](https://code.visualstudio.com/download))
- [Nodejs](https://nodejs.org/en/) installed.
- [Git](https://git-scm.com/downloads) installed.
- [Preact](https://preactjs.com/)

## What is Signal?

Signal is a state management tool or library that allows developers to subscribe to state changes and dispatch actions to update the state. Using it to manage state in applications has several advantages, including: 

- Enabling quick rendering of state changes without requiring a complex build setup.
- Simple to use and time-saving by providing a set of APIs.

### How does Signal work?

Signal uses values that can be observed for changes called [**Observables**](https://en.wikipedia.org/wiki/Observer_pattern) to efficiently keep track of the state of applications and ensure that the components are updated when the state changes. Components in an application can subscribe to Observables to observe events that cause a change in the state. Signal automatically updates the state of the components when the observable value changes.

Using Signal to manage state, your applications will always be up to date with the most recent data. Signal is tightly coupled with and mostly used with [Preactjs](https://preactjs.com/), among others.

### Benefits of Signal Over state hooks

Compared to state hooks, Signal offers several advantages, including efficient state updates regardless of whether the state is global, passed via props or context, or local to a component.

Another benefit is the ability to use Signal inside or outside of your application's components and to work with hooks and class components.

Other benefits include:

- **Efficient updates**: When the Signal's dependencies are updated, the components and effects that depend on the Signal's value remain unchanged. However, the components and effects will only be affected when the Signal's value changes. Moreover, when the hooks' dependencies are updated, the components change.
- **Optimal dependency tracking**: Preact framework seamlessly works with Signal by keeping track of the components that depend on the Signal, unlike hooks architecture which works by creating dependency arrays. 
- **Direct access**: Accessing the value of a signal in a component automatically subscribes to updates, eliminating the need for selectors or hooks.


## DEMO: Setting up the Project

In this tutorial, you'll build a Budget application with Preact. To start with Signal, you will need the [preact/signal](https://www.npmjs.com/package/@preact/signals-react) npm package. 

*The complete source code of the project can be found* [*here*](https://github.com/debemenitammy/Budget-Application)*.*

Start by setting up a new Preact project, "**budget-application**," by running this command in your terminal:

```
npx preact-cli create default budget-application
```

Afterward, your project directory will be created on your local machine.


![1](https://blog.openreplay.com/images/managing-state-with-signal/images/image01.png)


Next, change into the directory of your project and install the `preact/signal` npm package by running this command:

```
cd budget-application
npm install @preact/signals
```

## Creating the State

Preact Signal will manage the state of the application's transactions and provide the necessary state mutations to allow for the updating, deleting, and retrieving up-to-date data from the state.

Begin by creating a "**store**" folder in your project, which will contain a "**budget.store.js**" file within the "**src**" directory.

Then, within the "**budget.store.js**" file, paste the following code:

```javascript
import { computed, signal } from "@preact/signals";
    
export const transactions = signal([
    { title: "Obi", type: "-", amount: 3000, uid: 0 },
    { title: "Obi", type: "+", amount: 30000, uid: 1 },
]);
    
export const totalAmount = computed(() =>
    transactions.value.reduce((p, c) => {
    if (c.type === "+") return p + +c.amount;
    if (c.type === "-") return p - +c.amount;
    }, 0)
);
    
export const expenses = computed(() => transactions.value.filter((e) => e.type === "-"));
    
export const incomes = computed(() => transactions.value.filter((e) => e.type === "+"));
    
export const addTransaction = (title, type, amount = 0) => {
    transactions.value = [
    ...transactions.value,
    {
        uid: transactions.value.length + 1,
        title,
        type,
        amount,
    },
    ];
};
    
export const removeTransaction = (uid) => {
    transactions.value = transactions.value.filter((t) => t.uid !== uid);
};
```

The code snippet above contains the following:

- A single signal state called `transactions` which manages data for the transaction records saved on the app. It has the following data structure:
    `Array<{ title: string, type: string, amount: number, uid: number }>.`
- Three computed states: `totalAmount`, `expenses`, and `incomes`. Using `computed` to create these states results in an immutable state that can cause subscribers to be re-rendered. It contains a filtered version of the original transaction state.
- Two state mutators: `addTransaction` and `removeTransaction`. These mutators are used to update the state transactions: `addTransaction` adds new transactions to the list, while `removeTransaction` removes data from the list.



<h2>Open Source Session Replay</h2> 

_<a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a> is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data._

![OpenReplay](https://blog.openreplay.com/banner-blog_1oYPGT.png)

_Start enjoying your debugging experience - <a href="https://github.com/openreplay/openreplay" >start using OpenReplay for free</a>._





## Adding the UI

Create a user interface for the application by pasting the code from this [repository](https://github.com/debemenitammy/Budget-Application/blob/main/src/routes/home/index.js) into your `routes > home > index.js`.

Next, you will create a component for the transactions. 

## Creating the TransactionView Component 

This component is an abstraction and one of the UI components used to render data.

Delete the "**header**" folder in the "**components**" directory and create a new file called "**transaction-view.js**" with the code from [here](https://github.com/debemenitammy/Budget-Application/blob/main/src/components/transaction-view.js).

Return to your "**index.js**" file in your "**routes > home**" directory and replace this line of code - `/* transaction component import goes here */` with the following import statement:

```javascript
import TransactionView from "../../components/transaction-view";
```

## Adding CSS

In your "**src > assets**" directory, create a "**css**" folder with a "**main.css**" file that contains this [style](https://github.com/debemenitammy/Budget-Application/blob/main/src/assets/css/main.css).

Then, replace the `/* import style here */` with the following to import “**main.css**" into "**router > home > index.js**":

```javascript
import "../../assets/css/main.css"
```

## Testing the Application

To test the application to ensure that it works, run the following command:

```
npm run dev
```

Afterward, you should see the following in your terminal:


![2](https://blog.openreplay.com/images/managing-state-with-signal/images/image02.png)


Go to the local URL "http://0.0.0.0:51963" to view the application in your browser:


![3](https://blog.openreplay.com/images/managing-state-with-signal/images/image03.png)


## Conclusion

Using Signal to manage state allows for real-time state management. In this article, you covered what Signal is and how it works, the advantages of Signal over State hooks, and how to set up a project with Preact Signal.

> A TIP FROM THE EDITOR: We discussed Preact at length in our [Alternatives to React: Preact](https://blog.openreplay.com/alternatives-to-react-preact) article.



[![newsletter](https://blog.openreplay.com/newsletter_Z1P0UIP.png)](https://newsletter.openreplay.com/)