New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@signalis/react

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@signalis/react

`@signalis/react` is the React integration library for `signalis`. It provides a Higher-Order Component that can be used to integrate React components with Signalis' reactivity system. In addition, `@signalis/react` provides a set of hooks for creating re

latest
npmnpm
Version
0.2.6
Version published
Maintainers
1
Created
Source

@signalis/react

@signalis/react is the React integration library for signalis. It provides a Higher-Order Component that can be used to integrate React components with Signalis' reactivity system. In addition, @signalis/react provides a set of hooks for creating reactive entities inside of React components in a way that integrates tightly with React's rendering cycle. Finally, as a convenience, @signalis/react also re-exports all of @signalis/core, if you're using signalis in a React app, you can just install @signalis/react and get access to the entirety of signalis.

reactor

reactor is the main integration point for @signalis/react. Use reactor to wrap any component that you want to rerender in response to changes in reactive values.

const count = createSignal(0);

const Counter = () => {
  return (
    <div>
      <span>Count: {count.value}</span>
      <button type="button" onClick={() => count.value++}>
        +
      </button>
      <button type="button" onClick={() => count.value--}>
        -
      </button>
    </div>
  );
};

export default reactor(Counter);

reactor works by wrapping the component passed to it in a Proxy that that tells the component to re-render any time any reactive value used inside the component updates. Since it returns a Proxy, the component should still share all the same properties that the base component does, which means it should show up in React DevTools the same way it would normally.

useSignal

useSignal is a React hook for creating a Signal inside of a React component. It has the following signatures:

useSignal<T>(initializer: () => T): Signal<T>;
useSignal(value?: null | undefined): Signal<unknown>;
useSignal<T extends {}>(value: T): Signal<T>;

useSignal will return a Signal just like createSignal does, except that it uses useMemo under the hood to persist the Signal throughout component re-renders.

Basic Usage

const Counter = () => {
  // Since we use `useMemo` under the hood, the Signal returned here will only be created once and is then re-used in subsequent rerenders.
  const count = useSignal(0);

  return (
    <div>
      <span>Count: {count.value}</span>
      <button type="button" onClick={() => count.value++}>
        +
      </button>
      <button type="button" onClick={() => count.value--}>
        -
      </button>
    </div>
  );
};

export default reactor(Counter);

Lazy Initialization

For expensive initial values, use a function initializer to defer computation until the signal is first created. The initializer function runs only once, not on every render:

const DataProcessor = () => {
  // ✅ Expensive computation only runs once
  const data = useSignal(() => processLargeDataset());

  return <div>Processed: {data.value.length} items</div>;
};

export default reactor(DataProcessor);

Note: Functions are always treated as initializers (matching React's useState pattern).

useDerived<T>(fn: () => T, deps?: DependencyList): Derived<T>

Similar to useSignal, useDerived is used to create a Derived inside of a React component. useDerived uses useRef and useMemo to ensure that the underlying Derived is only created once and is then re-used on subsequent rerenders.

Basic Usage

const Counter = () => {
  const count = useSignal(0);
  const isOdd = useDerived(() => count.value % 2 !== 0);

  return (
    <div>
      <span>Count: {count.value}</span>
      <span>The count is {isOdd.value ? 'odd' : 'even'}</span>
      <button type="button" onClick={() => count.value++}>
        +
      </button>
      <button type="button" onClick={() => count.value--}>
        -
      </button>
    </div>
  );
};

export default reactor(Counter);

Mixed Dependencies

When your derived computation depends on both signals and non-signal values (like props, useState, or useContext), you must pass those non-signal values in the deps array. The derived will recreate when the deps change, and signal reactivity will continue to work automatically.

const ProductPrice = ({ taxRate }) => {
  const price = useSignal(100);
  const total = useDerived(() => price.value * (1 + taxRate), [taxRate]);
  // Updates when taxRate prop OR price signal changes

  return (
    <div>
      <div>Price: ${price.value}</div>
      <div>Tax Rate: {taxRate * 100}%</div>
      <div>Total: ${total.value}</div>
      <button onClick={() => (price.value += 10)}>Increase Price</button>
    </div>
  );
};

export default reactor(ProductPrice);

Important: Just like with useEffect, you must include all non-signal dependencies in the deps array. If you forget to include a prop, state, or context value that your derived uses, it will have a stale closure and won't see updates to that value.

// ✅ Good: All non-signal dependencies listed
const total = useDerived(() => price.value * taxRate, [taxRate]);

// ✅ Also good: Signal-only derivations don't need deps
const doubled = useDerived(() => count.value * 2);

// ❌ Bad: Missing taxRate in deps - will use stale taxRate
const total = useDerived(() => price.value * taxRate); // taxRate never updates!

useSignalEffect(fn: () => void | (() => void), deps?: DependencyList): void

useSignalEffect is a hook that allows you to create reactive effects inside of React components. It functions similarly to useEffect except that it automatically tracks any signal dependencies and will recompute whenever they change. useSignalEffect uses useEffect under the hood and returns the underlying effect's cleanup function so it will be automatically cleaned up the same way a regular useEffect will.

Basic Usage

const Counter = () => {
  const count = useSignal(0);
  const isOdd = useDerived(() => count.value % 2 !== 0);

  useSignalEffect(() => {
    // Runs on mount and whenever isOdd changes
    console.log(`The count is ${isOdd.value ? 'odd' : 'even'}`);
  });

  return (
    <div>
      <span>Count: {count.value}</span>
      <span>The count is {isOdd.value ? 'odd' : 'even'}</span>
      <button type="button" onClick={() => count.value++}>
        +
      </button>
      <button type="button" onClick={() => count.value--}>
        -
      </button>
    </div>
  );
};

export default reactor(Counter);

Mixed Dependencies

When your effect depends on both signals and non-signal values (like props, useState, or useContext), you must pass those non-signal values in the deps array, just like with useEffect. The effect will recreate when the deps change, and signal reactivity will continue to work automatically.

const UserProfile = ({ userId }) => {
  const refreshCount = useSignal(0);

  useSignalEffect(() => {
    // Effect runs when:
    // 1. Component mounts
    // 2. userId prop changes (via deps array)
    // 3. refreshCount signal changes (via signal reactivity)
    fetchUserData(userId, refreshCount.value);
  }, [userId]); // Must include userId in deps!

  return (
    <div>
      <button onClick={() => refreshCount.value++}>Refresh</button>
    </div>
  );
};

export default reactor(UserProfile);

Important: Just like with useEffect, you must include all non-signal dependencies in the deps array. If you forget to include a prop, state, or context value that your effect uses, it will have a stale closure and won't see updates to that value.

// ✅ Good: All non-signal dependencies listed
useSignalEffect(() => {
  api.call(userId, apiKey, count.value);
}, [userId, apiKey]);

// ✅ Also good: Signal-only effects don't need deps
useSignalEffect(() => {
  console.log(count.value);
}); // Defaults to [] (runs once on mount, then whenever signals change)

// ❌ Bad: Missing userId in deps - will use stale userId
useSignalEffect(() => {
  fetchUser(userId, count.value);
}); // userId never updates!

Keywords

reactivity

FAQs

Package last updated on 05 Oct 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts