1.3.8 • Published 2 years ago

react-use-signals v1.3.8

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

React-Use-Signals

This package is aimed to provide a comfortable and easy to use state management solution for React.

It is inspired by Vue's Signals API and is based on their Reactivity in Depth Article.

Installation

For NPM users:

npm install react-use-signals

For Yarn users:

yarn add react-use-signals

Usage

Creating a Signal

// counterSignal.js
import { createSignal } from 'react-use-signals';

export const counterSignal = createSignal(0);

export const handleIncrement = () => {
  counterSignal.value += 1;
};

Using a Signal

import { counterSignal, handleIncrement } from './counterSignal';

const Counter = () => {
  const count = counterSignal.useStateAdapter();

  return (
    <div>
      <p>Count: {count.value}</p>
      <button onClick={handleIncrement}>Increment</button>
    </div>
  );
};

Reactivity

As you can see in the example above, the Counter component is subscribed to the counterSignal and will be re-rendered whenever the signal's value changes.

The example uses the useStateAdapter hook to create a local state for your component that is automatically updated whenever the signal's value changes.

Utility functions like handleIncrement in the example above can be used to update the signal's value and called from anywhere in your application, even outside of React components.

This eliminates the need for prop drilling and setters and makes it easy to share state between components.

Complex Data Structures

Signals can hold any type of data, including complex data structures like objects and arrays.

// userSignal.js

import { createSignal } from 'react-use-signals';

export const userSignal = createSignal({
  name: 'John Doe',
  age: 42,
  address: {
    street: '123 Main St',
    city: 'New York',
    state: 'NY',
    zip: '10001',
  },
});

export const handleUpdateName = (name) => {
  userSignal.value.name = name;
};

export const handleUpdateStreet = (street) => {
  userSignal.value.address.street = street;
};
import { userSignal, handleUpdateName, handleUpdateStreet } from './userSignal';

const User = () => {
  const user = userSignal.useStateAdapter();

  return (
    <div>
      <p>Name: {user.value.name}</p>
      <p>Street: {user.value.address.street}</p>

      <input
        type="text"
        value={user.value.name}
        onChange={(e) => handleUpdateName(e.target.value)}
        />
        <input
          type="text"
          value={user.value.address.street}
          onChange={(e) => handleUpdateStreet(e.target.value)}
        />
    </div>
  );
};

Effects

There are two ways to create effects with Signals.

1. Using the useEffect hook

Signals can be used with the useEffect hook just like any other React state.

import { counterSignal } from './counterSignal';

const Counter = () => {
  const count = counterSignal.useStateAdapter();

  useEffect(() => {
    console.log(`Count: ${count.value}`);
  }, [count.value]);

  return (
    <div>
      <p>Count: {count.value}</p>
      <button onClick={handleIncrement}>Increment</button>
    </div>
  );
};

2. Using the signalEffect function

The signalEffect function allows you to create a function that will be called whenever the signal's value changes. It is similar to the useEffect hook, but is designed to be used outside of React components.

Furthermore, it automatically knows which signals are used inside the function and doens't require a dependency array.

import {signalEffect} from 'react-use-signals';
import { counterSignal } from './counterSignal';

signalEffect(() => {
  console.log(`Count: ${counterSignal.value}`);
});

Typescript

Signals can be used with Typescript by providing a type argument to the createSignal function.

import { createSignal } from 'react-use-signals';

type User = {
  name: string;
  age: number;
};

export const userSignal = createSignal<User>({
  name: 'John Doe',
  age: 42,
});

If no type argument is provided, the signal will infer the type from the initial value. This can become problematic when the initial value is null or undefined, or an empty array or object.

The signal itself is a generic type that takes the type of the initial value as an argument.

import { createSignal, Signal } from 'react-use-signals';

type User = {
  name: string;
  age: number;
};

export const userSignal: Signal<User> = createSignal({
  name: 'John Doe',
  age: 42,
});

Stay in touch

If you have any questions or suggestions, feel free to open an issue on Github.

1.7.7

2 years ago

1.7.3

2 years ago

1.7.5

2 years ago

1.7.2

2 years ago

1.7.1

2 years ago

1.7.0

2 years ago

1.5.5

2 years ago

1.5.3

2 years ago

1.5.2

2 years ago

1.5.1

2 years ago

1.5.0

2 years ago

1.4.9

2 years ago

1.4.8

2 years ago

1.4.7

2 years ago

1.4.6

2 years ago

1.4.5

2 years ago

1.4.4

2 years ago

1.4.3

2 years ago

1.4.2

2 years ago

1.4.1

2 years ago

1.4.0

2 years ago

1.3.9

2 years ago

1.3.8

2 years ago

1.3.7

2 years ago

1.3.6

2 years ago

1.3.5

2 years ago

1.3.3

2 years ago

1.3.2

2 years ago

1.3.1

2 years ago

1.3.0

2 years ago

1.2.1

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

1.0.0

2 years ago