-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: useState(..)
#22
Comments
Here's an alternate approach that I think addresses some of the above limitations: doWithState(component).run({});
function *component({ useState, }) {
var [ id, updateID ] = yield useState(() => Math.floor(Math.random() * 1000));
console.log(`random ID: ${id}`);
id = yield updateID(42);
console.log(`fixed ID: ${id}`);
} And the implementation of function doWithState(gen,...args) {
var state = { nextSlotIdx: 0, slots: [], };
return IO(env => {
state.nextSlotIdx = 0;
var context = { ...env, useState, };
return IO.do(gen,...args).run(context);
});
// ********************************************
function useState(initialVal) {
return IO(env => {
var slots = state.slots;
var curSlotIdx = state.nextSlotIdx++;
if (!(curSlotIdx in slots)) {
if (typeof initialVal == "function") {
initialVal = initialVal();
}
slots[curSlotIdx] = initialVal;
}
return [
slots[curSlotIdx],
function update(nextVal){
return IO(() => {
if (typeof nextVal == "function") {
nextVal = nextVal(slots[curSlotIdx]);
}
return (slots[curSlotIdx] = nextVal);
});
},
];
});
}
} |
A further refinement to the doWithState(component).run({});
function *component({ useState, useSharedState, }) {
var [ id, updateID ] = yield useState(() => Math.floor(Math.random() * 1000));
var [ greeting, updateGreeting ] = yield useSharedState("greeting","Hello World!");
console.log(`random ID: ${id}`);
id = yield updateID(42);
console.log(`fixed ID: ${id}`);
console.log(greeting);
} And this implementation: const privateStateKeys = new WeakMap();
const SHARED_STATE = Symbol("shared-state");
function doWithState(gen,...args) {
return withState(IO.do(gen,...args),gen);
}
function doXWithState(gen,deps,...args) {
return withState(IOx.do(gen,deps,args),gen);
}
function withState(io,gen) {
if (!privateStateKeys.has(gen)) {
privateStateKeys.set(gen,Symbol(`private-state:${gen.name || gen.toString()}`));
}
const PRIVATE_STATE = privateStateKeys.get(gen);
return IO(env => {
var {
[PRIVATE_STATE]: privateState = { nextSlotIdx: 0, slots: [], },
[SHARED_STATE]: sharedState = {},
} = env;
env[PRIVATE_STATE] = privateState;
env[SHARED_STATE] = sharedState;
privateState.nextSlotIdx = 0;
return io.run({
...env,
useState,
useSharedState,
});
});
// ********************************************
function useState(initialVal) {
return IO(({ [PRIVATE_STATE]: privateState, }) => {
return accessState(
privateState.slots,
privateState.nextSlotIdx++,
initialVal,
env => env[PRIVATE_STATE].slots
);
});
}
}
function useSharedState(stateName,initialVal) {
return IO(({ [SHARED_STATE]: sharedState, }) => {
return accessState(
sharedState,
stateName,
initialVal,
env => env[SHARED_STATE]
);
});
}
function accessState(stateStore,prop,initialVal,getStateStore) {
if (!(prop in stateStore)) {
if (typeof initialVal == "function") {
initialVal = initialVal();
}
stateStore[prop] = initialVal;
}
return [
stateStore[prop],
function update(nextVal){
return IO(env => {
var stateStore = getStateStore(env);
if (typeof nextVal == "function") {
nextVal = nextVal(stateStore[prop]);
}
return (stateStore[prop] = nextVal);
});
}
];
} |
Taking inspiration from Hooks (i.e., React), a state preserving mechanism like
useState(..)
is proposed.You could use it in do-routines like this:
There are some unresolved issues with such a mechanism:
nextSlotIdx
needs some way to be reset between invocations of thecomponent(..)
Here's a candidate first implementation:
The text was updated successfully, but these errors were encountered: