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

react-hook-signal

v0.0.1-rc.17

Published

<img src="https://github.com/arif-rachim/react-hook-signal/raw/main/assets/react-hook-signal-hero.png" width="830" alt="react hook signal, seamless way to integrate React with TC39 Signal Proposal">

Downloads

28

Readme

Commitizen friendly codecov Node.js CI npm bundle size

React-Hook-Signal is a tiny library, less than 1kb. It helps you integrate Signal with your React components easily.

Installation

npm install react-hook-signal signal-polyfill

What are Signals?

The TC39 Proposal for Signals in JavaScript aims to establish a mechanism for components to communicate effectively. This proposal includes a polyfill for prototyping purposes.

Understanding Signals

  • Refer to https://eisenbergeffect.medium.com/a-tc39-proposal-for-signals-f0bedd37a335 for detailed explanation.
  • Explore the proposal repository: https://github.com/proposal-signals/proposal-signals

Once adopted, JavaScript will have a native signaling system, referred to as Signal throughout this guide.

How signal can efficiently re-render react component

Solving rerendering problem in react using signal

In React components, re-rendering starts at the component's beginning and extends to the end of the JSX element. Signal usage allows precise re-rendering, boosting performance and simplifying development without the need for memoization or useCallback functions.

Why choose React-Hook-Signal?

  • It's straightforward: Just React and Native Signal, no extra babel plugin needed.
  • Enjoy full TypeScript support for an improved Developer Experience.
  • Flexibility is key: Opt-in for integration in your React project, seamlessly blending state and signal.
  • It's incredibly lightweight, clocking in at less than 1kb

Steps to Integrate Signals with React

STEP 1: Rendering Signal Values:

  • Utilize notifiable components provided by react-hook-signal.
  • notifiable components accept standard HTML attributes, Signal, and Lambda for detecting dependency changes.

Example:

// Global.tsx
import {Signal} from "signal-polyfill";
import {JSXAttribute} from "react-hook-signal";

export const count = new Signal.State(0)
export const renderCount = new Signal.Computed(() => {
    return <div>Count {count.get()}</div>
})

The fastest way to integrate these Signals is to use the notifiable components.

import {count,renderCount} from "./GlobalSignals.tsx";
// here we are importing react-hook-signal:notifiable
import {notifiable} from "react-hook-signal";


export function App() {
    return <>
    
        {/* When user click button it will update the state */}
        <button onClick={() => count.set(count.get() + 1)}>Click here</button>
    
        {/* Following line will get auto update when user click button*/}
        <notifiable.div>{renderCount}</notifiable.div>
    </>
}

notifiable component attributes is not only capable of accepting the Signal type but also can receive Lambda

Lambda is a callback that's able to listen for changes in the signals it depends on.

import {count} from "./GlobalSignals.tsx";
import {notifiable} from "react-hook-signal";


export function App() {
    return <>
    
        {/* When user click button it will update the state */}
        <button onClick={() => count.set(count.get() + 1)}>Click here</button>
    
        {/* Following line will get auto update when user click button*/}
        <notifiable.div>{() => {
            return <div>Count {count.get()}</div>
        }}</notifiable.div>
    </>
}

STEP 2: Observing Signal Changes

  • Use the useSignalEffect hook to listen for changes in Signal.
  • This hook accepts a callback that reads the final signal value and can optionally return a cleanup function.

Important Note:

  • useSignalEffect doesn't automatically re-render the component. Use React.useState to trigger a re-render.

Example:

import {count} from "./GlobalSignals.tsx";
import {useSignalEffect} from "react-hook-signal";
import {useState} from "react";

export function App() {
    const [countState,setCountState] = useState(count.get())
    
    useSignalEffect(() => {
        // Here, within the useSignalEffect hook, I can listen for updates on any Signal.State or Signal.Computed
        setCountState(count.get())
    })
    return <div style={{display:'flex',flexDirection:'column',alignItems:'center'}}>
        {/* When user click button it will update the state */}
        <button onClick={() => count.set(count.get() + 1)}>Click here</button>

        {/* Following line will be updated because of countState updated*/}
        <div>{countState}</div>
    </div>
}

STEP 3: Creating Signals in React Components:

  • useSignal is a hook that creates Signal.State, and useComputed is a hook that creates Signal.Computed.

  • These hooks generate signals that are linked to the component's lifecycle.

  • To create a Signal.State, simply provide a constant value as a parameter when calling useSignal.

  • To create a Signal.Computed,simply provide a Lambda that returns the result of a dynamic computation.

Example :

import {notifiable, useSignal, useComputed} from "react-hook-signal";

export function App() {
    
    // creating Signal.State count
    const count = useSignal(0);
    
    // creating Signal.Computed countString
    const countString = useComputed(() => (count.get() * 2).toString());
    
    // creating Signal.Computed style
    const style = useComputed(() => {
        const isEven = count.get() % 2 === 0;
        return {
            background: isEven ? 'white' : 'black',
            color: isEven ? 'black' : 'white'
        }
    })

    // creating Signal.Computed text
    const text = useComputed(() => {
        const isWhite = style.get().background === 'white'
        return <div>{isWhite ? 'Background is White' : 'Background is Black'}</div>
    })

    return <div style={{display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
        {/* When user click button it will update the state */}
        <button onClick={() => count.set(count.get() + 1)}>Click here</button>

        {/* Following line will never get auto update*/}
        <div>{countString.get()}</div>

        {/* Following line will get auto update when user click button*/}
        <notifiable.div>{countString}</notifiable.div>

        {/* Following line will get auto update when user click button*/}
        <notifiable.div style={style}>{text}</notifiable.div>
    </div>
}

STEP 4: Encapsulate any Component with a Notifiable :

  • Use Notifiable component to wrap any React Functional or Class Component
  • A React component encapsulated within the Notifiable component will inherently enable its properties and children to utilize Lambda expressions or Signals seamlessly

Example :

import {Notifiable} from "react-hook-signal";

export function App() {
    const count = useSignal(0);
    
    return <div style={{display:'flex',flexDirection:'column',alignItems:'center'}}>
        {/* When user click button it will update the state */}
        <button onClick={() => count.set(count.get() + 1)}>Click here</button>

        {/* Following line will be updated because of count updated*/}
        <Notifiable component={MyComponent} title={() => {
            return count.get() + ' Times'
        }}></Notifiable>
                    
    </div>
}

function MyComponent(props:{title:string}){
    return <div>Here is the title {props.title}</div>
}

Summary

The integration of Signal into the React application can be done in various ways tailored to the needs and complexity of the app.