re-js / remini Goto Github PK
View Code? Open in Web Editor NEWEasy to learn global state for React
License: MIT License
Easy to learn global state for React
License: MIT License
const $user = box({ name: 'Joe', email: '[email protected]' });
modify($user).name = 'John Doe'
The central part of any complex application is stateful logic. Application has a state and a logic that uses and modifies the state.
For example, according to Redux architecture the one state, and logic inside sagas, thunks, reducers, or action creators.
Remini proposal (suppose) pattern combined great ideas from Redux, Vue, and Angular. In depends on your internal particularities, you can choose one of the supposed implementations. The first one will be better for Redux-familiar developers.
When the center of our stateful logic is the Store.
const User = () => {
$state = box(initialState);
const login = () => {
update($state, state => { ...state, loggedIn: true });
}
const logout = () => {
update($state, state => { ...state, loggedIn: false });
}
return Object.assign($state, {
login,
logout
});
}
And the second one is the "flat style". All modules should be reactive transparently, looks like simple usual objects.
const User = () => {
$name = box('Amelia');
$loggedIn = box(false);
const login = () => {
put($loggedIn, true);
}
const logout = () => {
put($loggedIn, false);
}
return {
get name() {
return val($name);
},
get logginIn() {
return val($logginIn);
},
login,
logout
});
}
Or what I suggest will only worsen the situation? Will make the bundle size bigger! And again it will create a bunch of painfully growing api!
My dear community, please help) I will be glad to hear your thoughts!
Cons of the current way:
Cons of the new way:
const title = box(0);
title._ += 10;
expr(() => title._ + 10).to((val) => console.log(val));
title.to((p) => console.log(p));
title.map(v => v + 10);
const ev = event();
ev.to(k => console.log(k));
ev.filter().map().to();
ev.fire();
const evFire = ev.fire;
evFire(); // I'm not sure, it looks like an unnecessary complication at the start. Maybe later.
const onDragFinish = event();
onDragFinish.fire();
onDragFinidsh.to(() => console.log('drag finished'));
const custom = expr(() => title._ + 10, (k) => title._ += k);
custom.to(onDragFinish);
custom._ += 10;
custom.write(20);
custom.read();
custom.update(v => v + 1)
custom.readonly()
ev.readonly()
//
useBox(title, /* [title] */); // deps unnecessary
useExpr(() => ({
title: title._,
custom: custom._,
valu
}), [valu]);
// support only one argument in `to`, break support prev value.
// also should be removed unused API (sync, once, cycle)
const activeRoute = box<Route | void>();
Should be very simple syntax:
on(() => shallow(read($b)), listener)
sync(() => shallow({ a: read($a).k.m, b: read($b).e.f }), $v);
wrap
map($a, (a) => shallow(a))
// or
box.shallow
wrap.shallow
on.shallow
on.once.shallow
sync.shallow
useBox.shallow
useBoxes.shallow
This is a decorator for returns value.
const $user = box({
name: 'Joe',
email: '[email protected]',
settings: {},
avatar: 'https://avatar.com/1.jpg'
})
const $avatar = map($user, user => user.avatar)
// new version
const $avatar = select($user, user => user.avatar)
The main reason: The decrease in result application bundle size.
If I can use lazy initialization, I can make isolated scopes and clear the state whole the app.
const b = box(0);
const n = wrap(() => get(b) + 1);
on(n, v => console.log('next', v);
// All of it should be lazy
I should deny of subscription to function expression, for example:
on(() => get(n), v => console.log('next', v)) // deny, no possible to make lazy subscription
After I can add the new function in a separate folder.
isolate(async () => {
await runApp();
});
After remini
can be used without dependency injections or providing service. Just standard modules!
cycle(fn) === sync(fn)
sync(fn, fn) !== sync(fn)
import { useBox } from '@remini/react';
import { useBox } from '@remini/preact';
const
{ sel, expr, box, untrack: _re_untrack, batch: _re_batch } = require('reactive-box'),
I should check it and understand browser support requirements.
//val(pending) or val(pending, 10)
val(x, val(x) + 1)
Rename val
api method to get
.
I think better to use, and more understandable and semantic.
// ./custom.store.ts
import { wrap, box, val } from "remini";
export const CustomStore = () => {
const initialState = {
address: {},
user: {}
};
const $store = box(initialState);
// example of performance optimization if store has a lot of often changes outside of "user" object
const $user = wrap(() => val($store).user);
return Object.assign($store, {
get user() {
return val($user);
},
// this will be enought for most cases
get address() {
return val($store).address;
},
// ... some methods where
})
}
And useful usage in everywhere in the code. React example:
// ./Custom.tsx
import { provide } from "provi";
import { useBox } from "remini/react";
const Custom = () => {
const custom = useBox(provide(CustomStore));
return (
<>
<b>{custom.user}</b>
<address>{custom.address}</address>
</>
)
}
or without hooks:
// ./Custom.tsx
import { provide } from "provi";
import { component } from "remini";
const Custom = component(() => {
const $custom = provide(Custom);
return (
<>
<b>{$custom.user}</b>
<address>{$custom.address}</address>
</>
)
})
when(
() => this.isDataCanBeLoaded,
() => {
this.load(this.rootStore.user.language);
}
);
This is synonym of
on(
() => this.isDataCanBeLoaded,
(val) => {
val && this.load(this.rootStore.user.language);
}
);
but not almost
const b = box(0)
when(b, console.log)
b(1) // output: 1
b(2) // nothing
b(3) // nothing
b(0) // nothing
b(2) // output: 2
Idea
Rename Remini "when" function to "wait", hmmm, think about
Inspired by:
preactjs/signals#307 (comment)
In reality
useMemo
computes once.
btw you can useuseState
useState(() => signal(item))[0]
Try It.
import { box, event, val } from "remini";
export const LocaleConfig = () => {
const $code = box('ru');
const setLocaleTrigger = trigger();
return {
get code() {
return val($code);
}
};
};
export const useCustom = hook((arg: any) => {
const a = read($a);
const b = read($b);
return { a, b }
})
We should decorate the standard JSX h function:
(similar preact in ts config)
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact",
}
}
May be it is possible:
const b = box(0);
const A = component(() => <i>{b}</i>)
Modern communities used "action" term for making some actions on data in store.
Global state for React with three functions
box.shallow()
on.shallow()
once.shallow()
sync.shallow()
wrap.shallow()
promiseNext.shallow()
useBoxShallow()
useSelector()
useSelectorShallow()
const Comp = () => {
const active = useSelector(homeRoute, state => state.active, [...deps])
}
const useStateBox = (fn)
const $user = useStateBox(() => {
return {
a, b, c
}
}, [a, b, c]);
And It's will be interesting to combine it with the "local" module.
const logic = useLocal(() => new Logic(a,b, $user), [a, b, $user])
const $loaded = box(false);
const waitFor = async () => {
await when(() => read($loaded));
};
observe
should be observer
.
For consistency with Mobx, for previously Mobx developers.
Reason:
observe - mean "to observe" it's an action. But decorator should be not an action.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.