npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

signalist

v0.1.11

Published

⚠️ The package is still in the experimental stage...

Downloads

13

Readme

Signalist

⚠️ The package is still in the experimental stage...

⚠️ The current performance is not as good as React Fiber: https://signalist-demo.vercel.app/

The meaning of the logo is that React is frozen.

Everything in signalist is a poor imitation of solidjs applied to React.

About Signalist

Signalist is a React library that allows for granular updates to elements at the attribute level, using the signal method to avoid full component re-renders.

Signalist focus on performance and simplicity. With Signalist, you can enjoy the benefits of using signals to manage your state, just like you would with SolidJS. This allows you to build reactive user interfaces that only re-render when necessary, improving the performance of your application.

Signalist improves performance by only updating the necessary attributes of the components, rather than re-rendering the entire component. This means that only the specific properties that need to be updated will be changed, resulting in faster and more efficient updates.

Signalist is fully compatible with the existing React ecosystem and components. You can use your favorite React libraries and tools, and still benefit from the performance improvements offered by Signalist.

Benefits

  • Signal-based state management for improved performance
  • No re-renders components, only updating the necessary attributes of the components
  • Compatible with the existing React ecosystem and components
  • Supports SSR
  • Supports Typescript
  • Lightweight and easy to use

Compatibility

Signalist is designed to be fully compatible with the existing React ecosystem and components. You can use your favorite React libraries and tools, and still benefit from the performance improvements offered by Signalist.

Getting Started

To get started with Signalist, install it using npm:

npm install signalist

Now, you can use the useSignal hook to create and subscribe to signals in your components:

import { useSignal, signalJSX } from "signalist";

function MyComponent() {
  const count = useSignal<number>(0);

  console.log("render once!");

  // signalJSX hooks, auto binding signal to elements
  return signalJSX(
    <div>
      <p>Count: {count}</p>
      <button onClick={() => count.value + 1}>Increment</button>
    </div>,
  );
}

APIs

  • signal: create global signal object
  • computed: use function subscribe some signals
  • useSignal: create signal in react component, it keep value in other react setState change.
  • signalJSX: binding react JSX to signal update DOM
  • If: Append or remove some element, when value signal change
  • For: Use list data or list signal render a list elements
  • signalStorage: signal object, auto load/save from localstorage, signalStorage is used in conjunction with useInitStorage to ensure hydration consistency during SSR.

Usage

Signal in props

import { useSignal, signalJSX, Signal } from "signalist";

function PageA({ count }: { count: Signal<T> }) {
  // no rerender, only reset div element textcontent:
  return signalJSX(<div>Count: {count}</div>);
}

function PageB({ count }: { count: Signal<T> }) {
  // no rerender
  return signalJSX(<div onClick={() => (count.value += 1)}>update value</div>);
}

function MyComponent() {
  const count = useSignal<number>(0);
  // no rerender
  return signalJSX(
    <div>
      <PageA count={count} />
      <PageB count={count} />
    </div>,
  );
}

computed

Use signal() in computed, computed can auto subscribe signal change, and return a new value

import { computed, useSignal, signalJSX } from "signalist";

function MyComponent() {
  const count = useSignal<number>(0);

  // style is typeof Signal<CSSProperties>
  const style = computed<CSSProperties>(() => ({
    // text() can subscribe
    // text.value only read value
    fontSize: text().length + "px",
    color: "#00f",
  }));

  return signalJSX(
    <div>
      <h2 style={style}>count: {count}</h2>
      <button onClick={() => (count.value += 1)}> add count</button>
    </div>,
  );
}

signal

signal is a native JavaScript method that can be used anywhere, in any framework, to trigger updates directly in React. However, when using signal inside a React component, you should use useSignal, which is just a useRef wrapper around signal, to prevent signal loss caused by React's setState. If you're using signalist exclusively and have never used React's setState, you can even use signal instead of useSignal throughout your project.

import { signal } from "signalist";

// Declare in Anywhere

const username = signal<string>("user-name");

// Other page component:
function PageA() {
  return signalJSX(<div>User name: {username}</div>);
}

// Other page component:
function PageB() {
  return signalJSX(<input onChange={(e) => (username.value += e.target.value)} />);
}

Effect

Sure, here's a possible README file for your GitHub repository:

effect is a signal subscription function that collects any signal() calls used within it, and re-executes the effect whenever the signals mutate. If you only want to retrieve the value of a signal without subscribing to it, you can use signal.value, which only reads the value without subscribing.

import React from "react";
import { signal } from "signalist";
import Effect from "@signalist/effect";

function MyComponent(props) {
  const [count, setCount] = React.useState(0);

  // Subscribe to the count signal and log its value
  effect(() => {
    console.log(signal(count));
  });

  const handleClick = () => {
    setCount(count + 1);
  };

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

In this example, the effect function subscribes to the count signal and logs its value whenever it changes. Whenever the count state is updated, the effect function will re-execute and log the new value of the count signal.

Using effect can simplify the process of subscribing to signals and executing code when they mutate. It provides a simple and intuitive syntax for handling signal subscriptions, making it easier to write efficient and performant React components.

Effect + component + global signal example:

import { signal, effect } from "signalist";

const userInfo = signal();

// Other page component:
function PageA() {
  effect(async () => {
    const data = fetch("/api/user-info?name" + username()).then((v) => v.json());
    userInfo.value = data;
  });
  return signalJSX(<div>User name: {username}</div>);
}

// Other page component:
function PageB() {
  const email = computed(() => userInfo().email);

  return signalJSX(
    <div>
      <input onChange={(e) => (username.value += e.target.value)} />
      <div>{email}</div>
    </div>,
  );
}

If component

Because without re-render, you can only do this.

The If component is a React component that serves as a replacement for the ternary operator in React. It allows you to conditionally render components based on a boolean expression, without having to resort to a ternary operator. To use the If component, import it into your React component and use it as follows:

import { computed, useSignal, signalJSX } from "signalist";
function MyComponent() {
  const show = useSignal<boolean>(false);
  // no rerender
  return signalJSX(
    <div>
      <button onClick={() => (show.value = !show.value)}>Change show</button>
      <If value={show}>
        <div>ok, i maby show</div>
      </If>
    </div>,
  );
}

For component

Because without re-render, you can only do this.

For Component

The For component is a React component that serves as a replacement for the map() function in React. It allows you to easily render a list of components based on an array of data, without having to manually iterate over the array and return a list of components.

In this example, the For component is used to render a list of items based on an array of data. The each prop specifies the array of data to iterate over, and the children of the For component are a function that takes two arguments: the item from the array and its index. The function returns the component to be rendered for each item in the array.

import { computed, useSignal, signalJSX } from "signalist";
function MyComponent() {
  const list = useSignal([]);
  // no rerender
  return signalJSX(
    <div>
      <input
        onChange={(e) => {
          list.value = [...list.value, e.target.value];
        }}
      >
        Change show
      </input>
      <For each={(list, index)}>{(item) => <div key={index}>{item}</div>}</For>
    </div>,
  );
}

For component props

The For component accepts the following props:

  • each: An array of data to iterate over.
  • children: A function that takes two arguments: the item from the array and its index. The function returns the element or component to be rendered for each item in the array.

With react state, useEffect

Slower than React by default, because every time setState is called in React, it recreates the signalJSX.

You may not need this use case, but it does work. Signalist is designed to cater to gradual migration of legacy React projects, hence its flexibility in accommodating various use cases.

You can use react main api:

import { useState } from "react";
import { computed, useSignal, signalJSX } from "signalist";

function MyComponent() {
  const [state, setState] = useState(0);
  const count = useSignal<number>(0);

  useEffect(() => {
    console.log("I mount");
    () => {
      console.log("I unmount");
    };
  }, []);

  return signalJSX(
    <div>
      {/* slowly: */}
      <button onClick={() => setState(state + 1)}> add react state</button>
      <h2 style={style}>count: {count}</h2>
      {/* faster: */}
      <button onClick={() => (count.value += 1)}> add count</button>
    </div>,
  );
}

signalStorage

signalStorage is a React component that can automatically persist state to local storage and supports secure SSR hydration. To ensure successful SSR hydration, it's use the useInitStorage hook in conjunction.

First, use the useInitStorage hooks at the root component of your application:

import { useInitStorage } from 'signalist';

const

function App() {
  useInitStorage();
  return (
    <div>
      {/* your app */}
    </div>
  );
}

Then, you can use the signalStorage hook in any component that needs to persist state, signalStorage will automatically persist to localhost, and will be reloaded after useInitStorage is executed:

import { signalStorage } from "signalist";

// auto load
const clicks = signalStorage("clicks", "");

function Counter() {
  return (
    <div>
      <p>Count: {clicks}</p>
      {/* auto save in change */}
      <button onClick={() => (clicks.value += 1)}>Increment</button>
    </div>
  );
}

License

Signalist is licensed under the MIT License. See the LICENSE file for more information.

Contributing

Contributions are welcome! See the CONTRIBUTING file for more information.