Protocol @@unitShape
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 to bind 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 to define a shape of a unit in your custom entity, and then use 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).