Skip to content

Instantly share code, notes, and snippets.

View AlexandrHoroshih's full-sized avatar
🎯
Focusing

Alexander Khoroshikh AlexandrHoroshih

🎯
Focusing
View GitHub Profile
@AlexandrHoroshih
AlexandrHoroshih / use-unit-protocol.md
Last active December 18, 2022 11:20
use-unit-protocol-v2

Протокол для useUnit

Универсальный протокол для переиспользования концепта useUnit из биндингов под разные UI-фреймворки для библиотек из экосистемы.

Контекст

В экосистеме Эффектора есть библиотеки, которые вводят свои кастомные сущности: Query из @farfetched/core, Route из atomic-router или modelFactory из effector-factorio. Эти кастомные сущности представляют собой некий объект, основные свойства которого являются юнитами эффектора.

Сейчас каждая из этих библиотек заводит свои собственные библиотеки биндингов к UI-фреймворкам, многие из которых заключаются в очень простых надстройках над биндингами эффектора, например:

@AlexandrHoroshih
AlexandrHoroshih / effector-protocl-symbol.md
Last active November 6, 2022 07:53
effector-protocol-symbol

RFC: Универсальный контракт для экосистемы эффектора

Эффектор предоставляет хорошие базовые примитивы для построения логики, поверх них можно строить другие абстракции.

Многие библиотеки в экосистеме вводят свои абстракции: Query из farfetched, Route из atomic-router и Factory из factorio, которые обычно представляют собой объект со сторами

Было бы здорово ввести некий стандарт коммуникаций, который бы, вместо кастомных биндингов на каждый случай, позволил делать так:

import { useUnit } from "effector-react"
const currentEnv = process.env.NODE_ENV || "prettier";
const withLogger = process.env.LOGGER === "true";
const babelPluginOverrides = {
prettier: {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],

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

Proposal

// rules are the same as for react hooks, order must not change
const [last, setLast] = game.useStash(0);
const next = (last + 1) < game.myBots.length ? last + 1 : 0;
setLast(next)
const current = game.myBots[last];
for (let i = 0; i < game.myBots.length; i++) {
const my = game.myBots[i];
const target = game.lib.findClosest(my, game.enemyBots);
console.log(context)
return {
type: "stuff",
context,
}
test('stuff', async () => {
// create new forked scope, which is completly independent
const scope = fork({
// apply modifications like initial store values in this scope
values: new Map()
.set($myStore, "value"), // changed value in $myStore specifically for this scope
handlers: new Map()
.set(myFx, mockHandler) // changed effect handler to mock one for this scope
});
@AlexandrHoroshih
AlexandrHoroshih / effector-history-wrap.ts
Created August 20, 2021 19:35
Effector history wrapper
// an option to create bindings to history
// usage is like
//
// export const historyUpdated = createEvent<HistoryUpdate>();
// export const clocks = createHistoryClocks();
//
// clocks have fields like `push, replace, go` and so on
// can be used like clocks.push({ to: "path" })
//
// wrapHistory({
@AlexandrHoroshih
AlexandrHoroshih / next-effector.ts
Last active March 8, 2023 12:12
next/router + effector
import singletonRouter from 'next/router';
import type { NextRouter } from 'next/router';
// import { createDomain } from 'effector';
import { root } from '../../src/core/root';
export const routerDomain = root.createDomain('router');
type NextRouterEventWithError = [any, string];
@AlexandrHoroshih
AlexandrHoroshih / bindings.ts
Last active April 24, 2024 05:13
effector + history
import { matchPath, RouteProps } from "react-router";
// historyUpdated event is subscribed to history via history.listen or any other way
export const createPathMatcher = <Match = unknown>(config: {
path: string | string[] | RouteProps;
clock?: Event<any> | Store<any> | Effect<any, any>;
}) => {
return sample({
source: historyUpdated,