Comments (9)
В opti-update updater управляет состоянием атома и его статусом, класс которого приведен выше. Сейчас статус - это отдельный атом, которыя я передаю в транзакцию. Этот статус я не могу неявно наследовать в computable.
console.log('update a, b, set status.pending:')
updater.transaction()
.set(a, '2')
.set(b, '2')
.run({
type: 'promise',
atom: a,
status: aStatus,
fetch() {
return Promise.resolve('3')
}
})
from cellx.
У них немного по разному сделана ленивость, isPending создаёт скрытую ячейку при первом обращении к нему, а getError при первом обращении к нему в формуле, то есть при подписке. Хотелось бы "в формуле" сделать и для isPending, но похоже не получиться, если же я объединю их в одну ячейку, то потеряю "в формуле" и для getError. Плюс нельзя будет подписаться отдельно на isPending или на getError, прийдётся подписываться на оба сразу и обрабатывать лишнее, например, изменения getError когда зависимость вычисляется только из isPending.
from cellx.
В случае fetch, pending неразрывно связан с error. Т.е. где error, там и pending требуется показать. Кода меньше получается и проще работать с такой цельной сущностью, тот же merge.
Например, в моем todomvc, с помощью компонента ServerLoadingView отображается либо индикатор, либо плашка с ошибкой.
А в TodoLayout используется ServerLoadingView.
(!status.complete)
? <ServerLoadingView status={status} />
: children
}
На проблему можно взглянуть под другим углом. Кроме самих атомов, есть еще как бы теневое состояние атомов, который сейчас "размазано" в isPending, isError. У этого теневого состояния есть свойство просачиваться в computables, комбинируясь по особому алгоритму (FetchStatus.merge). Сейчас это у тебя уже реализовано, только в виде отдельных податомов.
Вот я и предлагаю решить задачу в общем виде, сделать точку расширения, что б сторонние библиотеки могли сами определять структуру этого теневого состояния и алгоритм его комбинации.
На мой взгляд api cellx несколько усложнен и есть тенденция к его разбуханию. isPending, getError по мне должны быть инкапсулированны в отдельный модуль.
Пример, вот все, что мой updater знает о cellx:
// @flow
interface Atom<V> {
set(val: V): void;
get(): V;
}
a, b, aStatus - атомы. Пример ниже обновляет a, b, ставит aStatus.pending выполняет fetch, по resolve ставит aStatus.complete и a = 3.
updater.transaction()
.set(a, '2')
.set(b, '2')
.run({
type: 'promise',
atom: a,
status: aStatus,
fetch() {
return Promise.resolve('3')
}
})
Все круто, но мне хотелось бы использовать механизм теневого состояния cellx. и получать aStatus из а, а не отдельный атом aStatus создавать, что бы этот aStatus протекал в computable.
Как-то так:
cellx.configure({mergeShadowState: FetchStatus.merge})
aStatus = a.createShadow(new UpdaterStatus())
from cellx.
Добавил Cell#getStatus
.
if (status.error) { newStatus.error = status.error newStatus.complete = false
завершение с ошибкой - это тоже вполне себе завершение, то есть complete должен переводиться в true.
from cellx.
правильнее было назвать success, когда нет ошибки и не pending.
Это свойство я ввел, т.к. проще логику строить.
function ErrorOrPendingComponent({status}: {status: FetchStatus}) {
if(status.error) {
return <Error error={status.error}/>
}
return <Loader/>
}
function Component({status}: {status: FetchStatus}) {
if (!status.complete) {
return <ErrorOrPendingComponent status={status}/>
}
return <div>Component</div>
}
from cellx.
Вспомнил, я делал по аналогии со спецификацией Observable: next, error, complete. И там complete не может быть с error.
Кстати, push/fail - это насколько я понимаю, велосипед Карловского, лучше завязываться на официальные спеки, на Observer {next, error, complete}.
observer.next("hello");
observer.next("world");
observer.complete();
from cellx.
В 1.6.77
заменил error на success.
Кстати, push/fail - это насколько я понимаю, велосипед Карловского
довольно удачный велосипед, Observable - это стримовая реализация, её нейминг не всегда удачно подходит для ячеек/атомов. Например, complete звучит как-то одноразово и это подходит стримам, но для ячейки вполне нормально вызвать reap несколько раз. У меня, наверное, плохо то, что калбек называется reap, а соответствующий метод dispose. Надо добавить reap, а dispose оставить его алиасом.
from cellx.
Добавил Cell#reap
.
from cellx.
Зачем вообще reap/dispose? разве subscribe/unsubscribe не тоже самое делают? подписался - счетичик в зависимостях +1, отписался счетчик-1, если === 0, то дергаем reap колбэк?
Ну как бы ни звучала, я на нее замахивался из-за упрощения интеграции со сторонними решениями.
Хоть хреновая, но спецификация, более формальная, чем чем event-emitter.
В принципе не столь важно, в opti-update я сделал обертку
Тут может не так очевидно, как с reactive-di. Вот компонент TodosView
export default function TodosView(
{todos}: TodosViewProps,
{theme}: TodosViewState
) {
return <ul className={theme.wrapper}>
{todos.items.map((todo: Todo) =>
<li className={theme.item} key={todo.id}>
<TodoView todo={todo}/>
</li>
)}
</ul>
}
Выглядит как react, flow и typescript понимают его props как реактовый, но он не зависит от реакта, это компонент с нулевыми зависимостями:
function TodosView(_ref, _ref2, __h) {
var todos = _ref.todos;
var theme = _ref2.theme;
return __h(
'ul',
{ className: theme.wrapper },
todos.items.map(function (todo) {
return __h(
'li',
{ className: theme.item, key: todo.id },
__h(_TodoView2.default, { todo: todo })
);
})
);
}
_CustomReflect2.default.defineMetadata('design:subtype', 'jsx', TodosView);
_CustomReflect2.default.defineMetadata('design:paramtypes', [{
theme: _TodosTheme2.default
}], TodosView);
Такой подход дает движок для рендеринга, react там или что-то, что поддерживает интерфейс React.createElement, отделить от кода приложения.
from cellx.
Related Issues (20)
- Guidance requested
- Untranslated part of README HOT 1
- Одно вычисление а не два HOT 2
- Please include Sodium FRP in your PERF
- Как сделать подписку с учётом будущих изменений? HOT 6
- Сломаны removeChangeListener и unsubscribe HOT 4
- dispose throws unexpectedly HOT 1
- why a varargs/overloaded API? HOT 2
- consider switching to Rollup HOT 5
- Good way to implement auto-run? HOT 3
- create-react-app TypeError: undefined has no properties _on EventEmitter.js:102 HOT 14
- Error rethrowed only once HOT 12
- Зачем `let reactions = this._reactions;` HOT 1
- Ожидание корректного значения HOT 1
- Почему dep._addReaction после pull делает ячейку DIRTY? HOT 1
- _deactivate() не чистит this._dependencies HOT 5
- После fail executon всея ячейки дерева state ACTUAL HOT 4
- Async cell HOT 3
- value instanceof EventEmitter. Подписка в конструкторе HOT 1
- "effects" in cellx HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cellx.