GithubHelp home page GithubHelp logo

Comments (28)

avkonst avatar avkonst commented on August 22, 2024 1

OK. will do this feature.

from hookstate.

avkonst avatar avkonst commented on August 22, 2024 1

The feature has been released in 1.4.0. Docs are here https://github.com/avkonst/hookstate#statelink

from hookstate.

avkonst avatar avkonst commented on August 22, 2024 1

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.

avkonst avatar avkonst commented on August 22, 2024

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.

lishine avatar lishine commented on August 22, 2024

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.

lishine avatar lishine commented on August 22, 2024

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.

avkonst avatar avkonst commented on August 22, 2024

"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.

avkonst avatar avkonst commented on August 22, 2024

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.

avkonst avatar avkonst commented on August 22, 2024

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.

avkonst avatar avkonst commented on August 22, 2024

"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.

avkonst avatar avkonst commented on August 22, 2024

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.

avkonst avatar avkonst commented on August 22, 2024

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.

lishine avatar lishine commented on August 22, 2024

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.

lishine avatar lishine commented on August 22, 2024

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.

avkonst avatar avkonst commented on August 22, 2024

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.

lishine avatar lishine commented on August 22, 2024

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.

lishine avatar lishine commented on August 22, 2024

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.

lishine avatar lishine commented on August 22, 2024

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.

avkonst avatar avkonst commented on August 22, 2024

from hookstate.

avkonst avatar avkonst commented on August 22, 2024

from hookstate.

lishine avatar lishine commented on August 22, 2024

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.

avkonst avatar avkonst commented on August 22, 2024

from hookstate.

lishine avatar lishine commented on August 22, 2024
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.

avkonst avatar avkonst commented on August 22, 2024

from hookstate.

avkonst avatar avkonst commented on August 22, 2024

from hookstate.

avkonst avatar avkonst commented on August 22, 2024

from hookstate.

lishine avatar lishine commented on August 22, 2024

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.

lishine avatar lishine commented on August 22, 2024

WOW

from hookstate.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.