Comments (28)
OK. will do this feature.
from hookstate.
The feature has been released in 1.4.0. Docs are here https://github.com/avkonst/hookstate#statelink
from hookstate.
I have integrated merge to one of my projects and dropped Mutate completely. it works great. Some advanced mutations are:
// array push:
state = useStateLink([]);
state.nested[state.nested.length].set('item')
// arrray pop:
state.nested[0].set(None)
// array swap:
state.merge(p => ({ 0: p[1], 1: p[0] }))
// array delete at index:
state.merge(p => ({ 0: None }))
// array delete last:
state.nested[state.nested.length - 1].set(None)
// or
state.merge(p => ({ [p.length - 1]: None }))
// object props swap
state = useStateLink({ a: 1, b: 2 })
state.merge(p => ({ b: p.a, a: p.b }))
// object prop drop
state.merge({ b: None })
// or
state.nested.b.set(None)
// object prop insert
state.nested['c'].set(3)
// or
state.merge({ c: 3 })
from hookstate.
Hi, you do not need to attach Mutate using 'with' function. Just use it, for example Mutate(state).merge(....). Where state is the result of useStateLink(FieldStore). PS sorry I am on mobile phone, not easy to write code.
For consistency, I think Mutate should allow attachment operation so it does not confuse anyone. What do you think?
from hookstate.
What do you mean by attachment operation?
What I would like - is to write state.merge(). Without need to write Mutate(state).merge.
Isn't 'with' is intended for this?
Another question, why is the .value or .get() api, why it is not possible access object directly state.a.b ?
BTW your lib is exactly the combination that I was looking for - using proxy(which gives a granular component updates according to usage) but with hooks api, so there is no need to wrap components.
I think it is the most beautiful combination nowadays.
The api though need some getting used to.
I have some experience with react state management - react-easy-state, easy-peasy, mobx, redux, parket.
from hookstate.
I understand the reason for the api. It is in order not confuse the use of state properties themselves, you write Mutate(state).merge, state.get(). But then maybe also better do like this get(state).a.b.
Another thing. The documentation says the state.set() is similar to setState, but it it is not. React setState({a: 1}) merges a into state.
from hookstate.
"React setState({a: 1}) merges a into state"
setState from class component merges the state. The setState
from React.useState
hook does not merge. Hookstate is a wrapper on top of the React.useState
hook, so it behaves the same way.
from hookstate.
The reason for Mutate and other plugins, is to make sure the core library is not bloated in size. Pull only what you need and not more. You can do state update with plain state.set(...)
just fine. Mutate
brings some convenience to this.
from hookstate.
Just checked the docs. It says: "it is similar to the setState variable returned by React.useState hook". So, it is correct - setState does not accept partial updates and does not merge it.
from hookstate.
"What do you mean by attachment operation?"
with
function effectively attaches the Plugin to the state, so the plugin can hook into state update notifications and do it's job. Not every plugin needs to subscribe to state updates, eg. Mutate, so does not require the attachment. However, for consistency it probably should do so.
What I would like - is to write state.merge(). Without need to write Mutate(state).merge.
Isn't 'with' is intended for this?
I see what you mean. This would require StateLink instance to be a proxy. In fact some earlier versions of the library allowed to do something like: state.extended.merge(...)
assuming 'merge' was injected by a plugin. However, I moved a way from this, because it was impossible to do type safe declaration of extension pluged in methods.
Another question, why is the .value or .get() api, why it is not possible access object directly state.a.b ?
Same thing here: this would require StateLink instance to be a proxy. Also, object props could be in a conflict with other important properties of StateLink like set
and nested
. nested
returns StateLinks of children. StateLink brings valuable functionality as you can pass it to other component in properties and use it to access/mutate the nested state the same as to mutate the root of the state.
I can advise you on more elegant way to set the state, if you tell me a bit more: what operations do you use from Mutate?
from hookstate.
I rarely need to use Mutate().merge(...)
for objects. Most of the time I set or or two of the nested fields, which can be done easily like this:
const state = useStateLink({ a: 1, b: 2 });
state.nested.a.set(p => p + 1) // sets only a, and keeps b
state.set(p => { ...p, a: p.a + 1 }) // same result as above
Mutate(state).merge(p => { a: p.a + 1 }) // same result as above
state.get() // returns the whole current object state
state.nested // returns states of children as an array of object, depending if state is an array or object.
from hookstate.
Regarding your proposed API without get()
. Let's say we could do something like this:
// !!! fake code, not Hookstate, just for explanation
const state = useStateLink({ a: 1, b: 2 })
state.a // returns 1
In this case we could implement the mutation API like this:
Mutate(state).set({ a: 2, b: 3})
However, we would not be able to do this (because it can not be implemented in JS nowdays):
Mutate(state.a).set(2)
Also Typescript types of variables like state
and state.a
would not imply if they are state variables and can be mutated. StateLink
brings strong type safety to this case.
from hookstate.
Thank you very much!
Sorry for stupid question, why there can be state.get state.set state.value state.nested but not state.merge ?
from hookstate.
Usually I will use merge({a: 1}) because I don't need usually the previous value.
Therefore it is the shortest way to express it.
In state.nested.a.set(a=>1) there is the addition of nested and repetition of a
from hookstate.
Sorry for stupid question, why there can be state.get state.set state.value state.nested but not state.merge ?
I guess it could have it. Currently there is no, because it is Mutate plugin, and because merge is not defined for primitive values. If we add merge to the StateLink, state.merge({a: 2})
would be the same as state.nested.a.set(2)
. Is the later much longer than the former? For multi fields update merge would still be better and shorter than calling set for each field. I actually have got plenty of cases, where I use merge for multi-field updates. So, maybe it is usual / required usecase for everybody. Merge would do the same action as set for primitive values. How does it sound?
If we add merge, I will need to revisit the value of the Mutate plugin. Maybe it should be partially incorporated to the core and partially dropped.... need to think about it.
from hookstate.
I didn't think that you can write state.nested.a.set(2).
Then it is shorter indeed.
But still unusual.
Even for one field update I would probably rather write write in this syntax state.merge({}) than state.nested.
Because I would not write(and read) 'nested' and because {} syntax is already usual
from hookstate.
I began to think, better add all the Mutate plugin to the stateLink. After all, these are the types you work with all the time in js: primites, objects, arrays. How much size it will add to the core lib?
But anyway, writing Mutate(state).merge also not such a big deal.
Another question came up - how you organize your whole app global state using this lib. And after looking at the doc, I see that you can take globalStore.nested.anotherStore and use in some part of the app. So all app state can be organized in a tree.
from hookstate.
I understand that you came up with this special api after a lot of thought and understanding and under js and js proxy limitations and because of the goals you wanted to achieve (such as types and performance), right?
If you write simply Store.subStore.a.b, and also create substores using factory function to add set, get and other methods. What goals you will miss?
from hookstate.
from hookstate.
from hookstate.
Could you please write an example of how it would look like with factory? I do not understand the proposal.
When using react-easy-state lib, something like this:
Const self = store({a: 1, ...commonFunctions(self)})
Export const Store = self
With react-easy-state there is no special syntax, it is a just reactive object inside react component.
from hookstate.
from hookstate.
import {UserStore} from './UserStore'
Const self = store({
a: 1,
user: UserStore,
...commonFunctions(self)
})
Export const GlobalStore = self
Const self = store({
name: "aaa",
...commonFunctions(self)
})
Export const UserStore=self
from hookstate.
from hookstate.
from hookstate.
from hookstate.
And it will be impossible to
create scoped state for properties which values hold primitive values like
numbers and strings.
Now I understand what you mean about scoped state.
With react-easy-state, for primitives, you would have to pass down the whole store or to create substore.
Here it is like each property is wraped with Store which you call Linkstate. Cool.
from hookstate.
WOW
from hookstate.
Related Issues (20)
- Example with zod? HOT 1
- Any showcase how to work with Immutables? HOT 2
- Resource leak with `useHookstate` HOT 2
- Is this lib still being updated? HOT 3
- Request: throw error when trying to assign nested state to a Proxy object HOT 2
- Migration from 3 to 4 HOT 4
- Localstored - optional initializer HOT 1
- https://hookstate.js.org/docs/exceptions/#hookstate-106 is killing me HOT 1
- What is the meaning of `E` in State<S, E>? HOT 1
- Injecting React-Router-dom instance into the store HOT 1
- one of my favourite projects really HOT 4
- More than 5 extensions loading HOT 2
- Creating a global object using hookstate, but unable to find the property when using it. HOT 2
- How to handle file objects in v4? HOT 1
- Isolating global states between tests HOT 4
- state.attach is not a function
- Combine extensions HOT 3
- Nextjs: localstorage is not defined HOT 6
- having problem with getting rid of proxy HOT 2
- Broadcasted state extension not working 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 hookstate.