1

Scenario:

Component A is parent of Component B.

A has a prop called a of type String.

B has a state called b of type Int.

b is 42

a is "hello"

Now I re-render A using render() and set a to be "hi!".

What happens to b ? Will it still be 42 after the re-render ? Why ?


Some related background questions about the why:

My initial guess is that 42 will get lost and the child component will be re-initialized with 0 or something default. But that would not make much sense, it would not be very useful, but I just don't see how the state of the child components will survive ?

Maybe I don't understand what is the difference between a stateful component and VDOM and how they relate to eachother.

1) Is a stateful component a template which is used to create a corresponding VDOM ? Is it so that the render() method takes a (stateful) component and spits out a VDOM and then this vdom is what will be rendered in the browser after render() created the vdom ?

2) Is it so that practically a stateless component equals a piece of VDOM but the same stateful component can generate many different VDOM-s ?

3) What is the mental model of react that I need to have in my head so that I can reason about this situation ? I think I am missing here something.

jhegedus
  • 20,244
  • 16
  • 99
  • 167
  • 1
    The quick answer is that b will still be 42 (https://jsfiddle.net/69z2wepo/79221/ try it here, update the child then the parent), the reason being that React has a VDOM (one only as far as I know) and all the manipulations happen there (because manipulating the DOM directly is expensive). Then the `reconciliation` happens and the DOM is synced with the VDOM with the minimum amount of changes needed (sorry for being vague). Now the component B gets re rendered, which means that the render method is called, but the state is not `reset`, because the B component does not get re instantiated. – G4bri3l May 22 '17 at 16:58
  • Maybe if you `unmount` the component and then `mount` it again then the state will be `reset` (because you instantiate a new component (?)) but I haven't tried that yet so you might wanna test it yourself. This https://facebook.github.io/react/docs/optimizing-performance.html#shouldcomponentupdate-in-action should help you get a visual understanding of a scenario for `reconciliation`, and in general the docs are a great place to understand React. – G4bri3l May 22 '17 at 16:59
  • Thanks, so the concept of component instance can explain this. The instance has a state and that state stays the same. So this should mean that props should be thought of as some kind of special **mutable** state (`var` in Scala, `var` in JS) ? My problem was that I was thinking that props are immutable fields (for example `final` in Java, `val` in Scala, `const` - I believe - in JS) of a component (a class) and then a new instance needs to be made (new component instantiated) if one wants to change the props. So that state will get lost, this is what was confusing me. – jhegedus May 22 '17 at 17:12
  • Because I thought that props are immutable and state is mutable. So now I have to change my worldview and think of props and state both as mutable variables ? Then what is the difference ? Confusing. – jhegedus May 22 '17 at 17:16
  • For example here: https://stackoverflow.com/a/26089687/1198559 it is written : "The React philosophy is that props should be **immutable** and top-down. " Now if props are immutable then if I modify props then I need to create a new instance of the component class as in any sensible programming language the only way I can "modify" an immutable field of an object if I create a new object with the modified field. – jhegedus May 22 '17 at 17:30
  • So props are immutable, if you change them you need to re instantiate the component, this involves re rendering the children but not necessarily re instantiating them, which means that their state is kept as it was. You are confusing the fact that we are changing the props of the Parent not the Child, so the state of the child is not changed and the Child gets not re instantiated. Now a good experiment to stretch this would be to update the state of the child, then pass it new props and see what happens. Let me see if I can update the fiddle. – G4bri3l May 22 '17 at 18:13
  • 1
    Again don't take my comments as a full answer to your question (if I was sure about it I would have posted an answer), I thought that engaging in a conversation with the question you raised could be helpful to find out if I really understand how it works. So take this more as of "let's research how it works together". – G4bri3l May 22 '17 at 18:15
  • Here is an updated fiddle (https://jsfiddle.net/69z2wepo/79229/) so apparently if I update the state of the child, then update its props (which we are thinking will re instantiate the component), the state persists. So I am not sure what happens under the hood but my feeling is that this behaves kind of like an `Object.assign`, where new props will override the old ones leaving everything else unchanged. – G4bri3l May 22 '17 at 18:43
  • Maybe the only actual way the state restores to default is if we `unmount` then `mount` again. – G4bri3l May 22 '17 at 18:43
  • 1
    Hmm, I start to have some idea: a component can be modelled as an object `Comp(prop, state)` where `Comp` also has a `render()` method that creates `VDOM` (using the current values of `prop` and `state`). When we update the immutable `prop` then we create a new `Comp` such that the state of the old `Comp` is copied to be the state of the new `Comp`. This would explain the observed behaviour. – jhegedus May 22 '17 at 19:13
  • I think this mental model could be more accurate, hopefully someone will provide a more detailed answer, I might do a bit more research on that later. Keep in mind that the `VDOM` is only one, so the render method updates the existing `VDOM`, which is much faster than updating the `DOM` directly. Then the `reconciliation` does the rest of the magic. – G4bri3l May 22 '17 at 19:16
  • 1
    Hm, I think that a new `VDOM` is created at each `render()` call because `VDOM` is immutable. – jhegedus May 22 '17 at 20:34
  • Oh yeah absolutely, sorry I misunderstood. I used poor wording, you are right! – G4bri3l May 22 '17 at 20:48
  • Hmm... this kinda shows something strange ... https://jsfiddle.net/69z2wepo/79234/ I wonder how to explain this... and this https://jsfiddle.net/69z2wepo/79237/ here one child looses the state and the other not... really strange.... – jhegedus May 22 '17 at 22:24
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/144878/discussion-between-g4bri3l-and-jhegedus). – G4bri3l May 22 '17 at 22:28

0 Answers0