info

Available since effector-react 22.4.0, effector-solid 0.22.7

Effector provides a way to use units (Stores, Events, Effects) in UI libraries with a special bindings like effector-react, effector-solid, etc. Normally, they allow binding any shape of units to a UI-framework:

import { createStore } from "effector";
import { useUnit } from "effector-react";

const $value = createStore("Hello!");

const Component = () => {
  const { value } = useUnit({ value: $value });

  return <p>{value}</p>;
};

But what if you want to create your own library on top of effector with some custom entities? For example, you want to create a router library with a custom Route entity, and you want to allow users to use it with effector-react bindings:

import { createRoute } from "my-router-library";
import { useUnit } from "effector-react";

const mainPageRoute = createRoute(/* ... */);

const Component = () => {
  const { params } = useUnit(mainPageRoute);

  return <p>{params.name}</p>;
};

It is possible with the @@unitShape protocol. It allows defining the shape of a unit in the custom entity and then using it in UI libraries. Just add field @@unitShape with a function that return shape of units to your entity:

function createRoute(/* ... */) {
  const $params = createStore(/* ... */);

  return {
    "@@unitShape": () => ({
      params: $params,
    }),
  };
}

FAQ


Q: How frequently @@unitShape-function is called?

A: As many times as useUnit itself is called – it depends on a UI-library. For example, effector-react calls it as any other hook – once per component render, but effector-solid calls useUnit once per component mount.


Q: How can I know what UI-library is used for particular @@unitShape call?

A: You cannot. @@unitShape has to be universal for all UI-libraries either has to check what UI-library is used inside by UI-library methods (like Context in React or Solid).

Contributors