Comments (17)
How about using a special proxy key to wrap the atomic value?
function Input({ value }) {
const onChange = useMutate(e => {
value.value = e.target.value;
})
return <input value={value.value} onChange={onChange} />
}
function App() {
const state = useBistate({
foo: 'some value'
})
// state.$foo for { value: 'some value' } and state.foo for 'some value'
// when 'some value' changes in `Input` component, update state.foo
return <Input value={state.$foo} />
}
from bistate.
I have no idea how to update state.foo from the child component to the parent component, since the child component just receives a string.
function Input({ value }) {
const onChange = useMutate(e => {
value.value = e.target.value;
})
return <input value={value.value} onChange={onChange} />
}
function App() {
const state = useBistate({
foo: 'some value'
})
// state.foo is a string, if we wrap state.foo inside Input, how to notify App?
return <Input value={state.foo} />
}
I suggest computed state
via useMemo.
function Input({ text }) {
const onChange = useMutate(e => {
text.value = e.target.value;
})
return <input value={text.value} onChange={onChange} />
}
function App() {
const foo = useBistate({ value: 'some value' } );
const bar = useBistate({ value: 'other value'});
// state is a plain javascript object
// do not mutate it
// treat it as read only
// useMemo guarantee the state always fresh when deps list changed
const state = useMemo(() => {
return {
foo: foo.value,
bar: bar.value
}
}, [foo, bar])
useEffect(() => {
// use state to do what you want
}, [])
return <Input value={foo} />
}
from bistate.
How about using a special proxy key to wrap the atomic value?
function Input({ value }) { const onChange = useMutate(e => { value.value = e.target.value; }) return <input value={value.value} onChange={onChange} /> } function App() { const state = useBistate({ foo: 'some value' }) // state.$foo for { value: 'some value' } and state.foo for 'some value' // when 'some value' changes in `Input` component, update state.foo return <Input value={state.$foo} /> }
Maybe it can make sense, but we must find a good way to support this pattern.
Instead of adding extra property key, binding(bistate, key)
function should be better, just like vue 3.0 reactivity api.
from bistate.
Let's think about it.
PR is welcome!!
from bistate.
I am working in the process for binding
features now~
from bistate.
I want to know your feeling about the binding
API below, it's ok to you or not?
function Input({ value }) {
const onChange = useMutate(e => {
value.value = e.target.value;
})
return <input value={value.value} onChange={onChange} />
}
function App() {
const state = useBistate({
foo: 'some value'
})
return <Input value={binding(state, 'foo')} />
// or
const foo = binding(state, 'foo')
return <Input value={foo} />
}
from bistate.
It's OK for this case.
But maybe we can do a more common design, use a Get/Set pair to specify the binding rule, and make some shorthands.
const foo = state.$foo
// is short for
const foo = binding(state, 'foo')
// is short for
const foo = binding(state, {
get: s => s.foo,
set: (val, s) => s.foo = val,
})
from bistate.
@littlehaker It's good, it looks even better if we use hooks
const foo = useBinding({
get: () => state.foo,
set: (value) => state.foo = value
})
from bistate.
I think the API names should be changed when the features become more general
const foo = useComputed({
get: () => state.foo,
set: value => state.foo = value
})
// or
const foo = useComputed(
() => state.foo,
value => state.foo = value
)
// and then
const useBinding = (state, key) => useComputed({
() => state[key],
value => state[key] = value
})
// we got
const foo = useBinding(state, 'foo')
from bistate.
from bistate.
@littlehaker Sorry for changing API frequently. But I found we maybe go too far away from our original purpose.
useComputed
accepts get/set function in function-component, it is too powerful to keep data consistent.
It's hard to prevent users write code like below. Tracing multiple bistate in computed
causes updating state indirectly, and less reasonable for now. We need more research to introduce them.
const foo = useComputed({
get: () => {
return [stateA.a, state.B.b]
},
set: value => {
stateA.a = value[0];
stateB.a = value[1]
}
})
I propose a new pattern for binding
API, non-selector-based, no hacky property like $foo.
function Input({ value }) {
const onChange = useMutate(e => {
value.value = e.target.value;
})
return <input value={value.value} onChange={onChange} />
}
function App() {
const state = useBistate({
foo: 'some value'
})
return <Input value={binding(state).foo} />
// or
const { foo } = binding(state)
// or
const { foo } = useBinding(state)
return <Input value={foo} />
}
Looking forward to your feedback!
from bistate.
The idea of Get/Set comes from use-profunctor-state.
Your newly revised API is good for objects, but its power is limited for data transform. For example:
const fahrenheit = useBistate({ value: 10 });
const celsius = useComputed({
get: () => fToC(fahrenheit.value),
set: (val) => fahrenheit.value = cToF(val),
});
// Cannot be done with binding
To avoid tracing multiple bistate while keeping the power, we may still offer a method to provide common Get/Set operation. Like below:
const foo = binding(state).foo
// is short for
const foo = binding(state, {
get: s => s.foo,
set: (val, s) => s.foo = val,
})
const celsius = binding(fahrenheit, {
get: (f) => fToC(f),
set: (c, f) => f.value = cToF(c),
});
from bistate.
@littlehaker I have tried some implementation, and I figured out that none of them is better than useMemo
with getter/setter
.
const celsius = useMemo(() => {
return {
get value() {
return fToC(fahrenheit.value)
},
set value(value) {
fahrenheit.value = cToF(value)
}
}
}, [fahrenheit.value])
is better than
let celsius = useComputed(
{
get: () => ({ value: fToC(fahrenheit.value) }),
set: ({ value }) => {
fahrenheit.value = cToF(value)
}
},
[fahrenheit.value]
)
It's easy and natural to handle multiple fields
const celsius = useMemo(() => {
let computed = {
get value() {
return fToC(fahrenheit.value)
},
set value(value) {
fahrenheit.value = cToF(value)
},
// add other fileds
get text() {
return `${computed.value}°`
}
}
return computed
}, [fahrenheit.value])
from bistate.
There is still some work we can do, such as handling stale closure, we may introduce useComputed
and useBinding
based on useMemo
let computed = useComputed({
get value() {
return fToC(fahrenheit.value)
},
set value(value) {
fahrenheit.value = cToF(value)
}
}, [fahrenheit.value])
let state = useBistate({ foo: 'abc' })
let { foo } = useBinding(state)
foo.value
from bistate.
@littlehaker useComputed and useBinding are implemented in bistate.
You can click the links above to see how to use.
Give me feedback when you have any question.
We will ship these features in version 1.3.0 later.
from bistate.
Hi @Lucifier129. It looks really nice, what a great work!
from bistate.
Thx, bistate v1.3.0 has been published to npm, it's available now.
from bistate.
Related Issues (1)
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 bistate.