As for now, every unit in effector must have an unique stable identifier and factories of units must be marked at effector/babel-plugin
settings in a special way by adding path to factory definiton to factories
list,
so every group of units created from factory call have ther own sids and other metadata.
As it turns out, this way can be really confusing for many developers and, while it fairly easy to use with external libs like patronum
or @effector/reflect
, this maybe hard to notice if something went wrong when dealing with project-specific custom factories
I think, if there is standardized api to define and use effector factories in the code
It can work as a pair of methods:
factory
First method to mark definiton of the factory, so babel-plugin can add some metadata to it, which can be useful for dev tools
import { factory, ... } from "effector"
export const createForm = factory((config) => ...)
// `factory` returns non-callable object
withFactory
Second method used for every call of factories:
import { withFactory } from "effector"
import { createForm } from "shared/lib/effector--my-forms"
const loginForm = withFactory(createForm, { fields: ... })
// making `factory` return non-callable object will ensure,
// that all effector factories created in the correct and detectable way
This way calls of custom factories are all marked by withFactory
and effector/babel-plugin
can add sid to every withFactory
call, just like for original methods like createEffect
- without additional configuration
Output of the plugin can be something like this:
const loginForm = withFactory({
fn: createForm.fn,
params: { fields: ... },
sid: "f78dsgkn9",
// some other metadata, if needed
})
Good parts:
- The explicit way of calling the factory allows you not to rely on a specific path - there is no need to keep track if another developer has moved the factory to a different location than the one specified in the babel-plugin settings
- I think special api is less confusing - it is basically "just write code like in the docs" versus "add import path of every custom factory to babel-plugin settings, make sure it is added in correct way, make sure there is no other ways to import this factory, etc"
- Current way of defining factories is still useful for external factories and libs like
@effector/reflect
(it is easy to just add the name of the lib tofactories
)
Problems:
- a lot of
withFactory
calls will be quite noisy in the source code. Maybe shorter name likef(createForm, config)
could help? - instead of path-related problems comes possible issue with
createStuff = (params) => withFactory(factory, params)
- nested factory call without wrapper at the top - since current path-based way cannot be removed, we will end up with to ways to do the same thing - both with different pros and cons
By the way, not so long ago, I made effector-factorio which uses a bit similar idea - you create factories with
modelFactory(config => ...)
method and then create instance provider hocs withmodelView(model, View)
. Although withoutwithFactory
method