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).