Skip to content
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

rethink props vs. state separation #209

Open
slimsag opened this issue Jun 25, 2018 · 5 comments
Open

rethink props vs. state separation #209

slimsag opened this issue Jun 25, 2018 · 5 comments

Comments

@slimsag
Copy link
Member

slimsag commented Jun 25, 2018

vecty:"prop" is confusing, and teaching the underlying semantics of why this is important is very hard (and will be even harder to people not familiar with React-like frameworks).

vecty:"prop" starts to feel like some sort of magic for beginners, which is very bad.

See this conversation starting here: https://gophers.slack.com/archives/C0LBM1R0C/p1529952138000073

One interesting idea to consider that @marwan-at-work proposed is just saying "there is no state" and only allowing components to have properties. This would mean that such state must ultimately be passed down from the parent, akin to Redux.

@progrium
Copy link

progrium commented Oct 3, 2018

I think not having state is a little... extreme. Why not just combine state and props? Vue.js basically does this except you have to declare props so it can properly validate templates. Also, I don't think vecty:"prop" is confusing, but there isn't a huge need for it until you start doing any kind of validation.

@nizsheanez
Copy link

"Not having state" is maybe not so bad idea if add sugar like hooks https://reactjs.org/docs/hooks-intro.html
But I worry about: React team moving it to "functional" paradigm direction, not sure that follow it in Golang will give any benefit.

@pyrossh
Copy link

pyrossh commented Jun 18, 2019

Hooks is something really good. I have been experimenting on it and it seems to make state handling very simple

@VinceJnz
Copy link

VinceJnz commented Aug 26, 2021

I haven't been able to find anything in the documentation about how this works but the discussion in slack has been very helpful.
Perhaps I'm missing something but could this be added to the documentation to explain how it currently works?

I should add that I have no experience with react so this is all new to me.

@VinceJnz
Copy link

Here are the notes I have made from the slack channel discussion.
Would it be possible to add this to the documentation somewhere?

vecty:"prop" struct

What does the 'vecty:"prop"' struct tag do?

Fundamentally, we have to be able to separate state and props fields somehow. The question is: how?

If this hasn’t changed since last time I ran into it, it basically instructs vecty to update the struct fields when calling vecty.Render with a new state. Otherwise, the old value will remain the same on the UI even if you rerender with a new value.

The reason we can't have this be the default behavour is because we need a way to separate "state" and "props" fields. For example, if your struct contained a counter variable that the component updated, you would expect that value to remain the same even if the parent component was re-rendered, so you would not want to tag it with 'vecty:"prop"'.

Why would the counter not remain the same if the parent component got rerendered?
For example, if a parent component renders a child component:

func (p *Parent) Render() vecty.HTMLOrComponent {
    return &Child{Counter: 0}
}

Whenever that parent is rerendered, it is returning a brand new instance of Child with Counter set to 0.
So there is the Child component from the last time Parent was rendered, and the Child component from this time the Parent was rendered.
Vecty needs to reconcile the two Child components somehow. So say that the first is Child has Counter == 10 and the second has Counter == 0 because that's what the parent set it to, the question is: Does Vecty copy that Counter variable from the new Child into the old one, or no?

In the React world, the answer is yes. The parent always rules. If you want to keep the old value then you copy that prop into a “sibling field” which would be the state field and the parent wouldn’t set the state field. So the state field should remain the same even if the parent rerendered itself. In fact, Go would actually enforce that rule if you make the state field private with lower case.

func (p *Parent) Render() vecty.HTMLOrComponent {
  return &Child{Counter: 0}
}
type Child struct {
    Counter 'vecty:"prop"'
    counter
}

func (c *Child)  Mount() {
  c.counter = c.Counter
}

My understanding is that React copies state from the new component to the old, just the same as we do effectively. The only difference in React is that you must explicitly place State and Props in separate objects, whereas in Vecty you must denote them with a struct tag.

In react you can’t even pass in state, because it’s an internal object. So props is the only thing you pass down of course, you can pass in a state value into a child prop, and if you mutate that value then it will get changed on the next render.

Vecty is the same as what you've described above, the only difference is that you can set a state fields initial value from the parent if you wish, rather than creating a phony prop value which ultimately gets transferred into the state value at component creation time.

If a parent component in React renders a child component twice, I think there still has to be two child component instances, and React has to reconcile the two somehow (e.g. by copying props from the "new" child instance into the "old" persistent child instance).

So I think they have the same problem ultimately: Which component inputs are properties, and which are state? React just separates the two by putting them into different objects.

Regarding using public vs. private fields

I think that can be confusing because you are then applying semantic meaning to public vs. private as being "public to the component" and "private to the component" rather than to the package. Effectively, you would be replacing 'vecty:"prop"' with whether or not a field is public or not. This could be very confusing when working in e.g. one Go package
this said another way, if you made a counter field public on a component, its value would no longer persist across renders which would be mighty confusing I think.

What matters to me the most is the mental model of the Vecty API. Coming from a React background, I just always expect the parent to be the ruler of the most updated values to a given prop, regardless of how many times it rerenders. If a child wants to keep its own state, then it just copies the value to another field during Mount time. I agree about the private/public comment you made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants