2.0 React comparison guide collaboration #364

Closed
chrisvfritz opened this Issue Aug 12, 2016 · 33 comments

Comments

Projects
None yet
5 participants
@chrisvfritz
Member

chrisvfritz commented Aug 12, 2016

@gaearon I've just updated the Scaling Up section of the Comparison with other Frameworks doc. If there's anywhere I've misrepresented create-react-app or have left out an important detail, please do let me know and I'll fix it. 馃槂

If you have thoughts on any other part of the React section, they'd also be very welcome! Maintaining accuracy and giving credit where its due are two very important goals of this document.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 12, 2016

Contributor

Sounds right 馃憤

Contributor

gaearon commented Aug 12, 2016

Sounds right 馃憤

@yyx990803

This comment has been minimized.

Show comment
Hide comment
@yyx990803

yyx990803 Aug 14, 2016

Member

I'll leave some ideas regarding the section here:

  • The tone could be less definitive in the CSS scoping section, and we should definitely mention CSS modules.
  • Some React users have concerns that the JSX vs. templates example is a bit esoteric which makes the "syntax noise" issue more prominent than it is, I've merged #368 and we probably want to revise the comparison accordingly.
Member

yyx990803 commented Aug 14, 2016

I'll leave some ideas regarding the section here:

  • The tone could be less definitive in the CSS scoping section, and we should definitely mention CSS modules.
  • Some React users have concerns that the JSX vs. templates example is a bit esoteric which makes the "syntax noise" issue more prominent than it is, I've merged #368 and we probably want to revise the comparison accordingly.
@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Aug 15, 2016

Member

@yyx990803 Just updated the CSS scoping language and slightly softened the syntax noise complaint. Thoughts?

Member

chrisvfritz commented Aug 15, 2016

@yyx990803 Just updated the CSS scoping language and slightly softened the syntax noise complaint. Thoughts?

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 15, 2016

Contributor

I'm a little concerned about this section:

Vue should then perform about 20 times as fast in this scenario

I understand you specifically said you don't want to provide any benchmarks, but in this case using specific numbers like this might give users the wrong impression. Can you show that Vue is 20 times faster than React in these scenarios? Or perhaps it might be better to rephrase this section to avoid such suggestions. (If Vue is 20 times faster, it is amazing, and I鈥檇 love to see this demonstrated!)

Contributor

gaearon commented Aug 15, 2016

I'm a little concerned about this section:

Vue should then perform about 20 times as fast in this scenario

I understand you specifically said you don't want to provide any benchmarks, but in this case using specific numbers like this might give users the wrong impression. Can you show that Vue is 20 times faster than React in these scenarios? Or perhaps it might be better to rephrase this section to avoid such suggestions. (If Vue is 20 times faster, it is amazing, and I鈥檇 love to see this demonstrated!)

@yyx990803

This comment has been minimized.

Show comment
Hide comment
@yyx990803

yyx990803 Aug 15, 2016

Member

@chrisvfritz re CSS scoping: I think we can still improve the section, because some people have been having success with certain CSS-in-JS solutions, and we should avoid suggesting there isn't any good ones out there, but rather focus on how approachable and frictionless Vue's scoping solution is (and the fact that it plays well with existing tools like postcss).

@gaearon it probably won't be after your recent optimizations ;) But yes, I agree we should avoid these "magic numbers" without benchmarks because people tend to take it seriously whenever there are numbers cited.

Member

yyx990803 commented Aug 15, 2016

@chrisvfritz re CSS scoping: I think we can still improve the section, because some people have been having success with certain CSS-in-JS solutions, and we should avoid suggesting there isn't any good ones out there, but rather focus on how approachable and frictionless Vue's scoping solution is (and the fact that it plays well with existing tools like postcss).

@gaearon it probably won't be after your recent optimizations ;) But yes, I agree we should avoid these "magic numbers" without benchmarks because people tend to take it seriously whenever there are numbers cited.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 15, 2016

Contributor

Yeah, hopefully it will be better 馃槃
The main issue for me is that it鈥檚 weird to both use exact numbers and not use benchmarks.

Contributor

gaearon commented Aug 15, 2016

Yeah, hopefully it will be better 馃槃
The main issue for me is that it鈥檚 weird to both use exact numbers and not use benchmarks.

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Aug 16, 2016

Member

@yyx990803 Just update the Component-Scoped CSS section again. Let me know if this is more what you had in mind.

@gaearon Just updated the JSX vs Templates section for the new code example you provided. Would love to hear your thoughts. I'm also thinking of replacing "20 times as fast" and similar numbers there with less concrete language like "significantly faster", then putting together a simple visualization demo that displays framerate, so that people can see how each performs on their own machine and browser - I personally prefer that to a benchmark, since it'll be in a real context. Would that sound good to you?

Member

chrisvfritz commented Aug 16, 2016

@yyx990803 Just update the Component-Scoped CSS section again. Let me know if this is more what you had in mind.

@gaearon Just updated the JSX vs Templates section for the new code example you provided. Would love to hear your thoughts. I'm also thinking of replacing "20 times as fast" and similar numbers there with less concrete language like "significantly faster", then putting together a simple visualization demo that displays framerate, so that people can see how each performs on their own machine and browser - I personally prefer that to a benchmark, since it'll be in a real context. Would that sound good to you?

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 16, 2016

Contributor

Yes, this sounds like a great proposition. 馃憤

Contributor

gaearon commented Aug 16, 2016

Yes, this sounds like a great proposition. 馃憤

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 16, 2016

Contributor

This is because JSX requires frequent compromises between readability and declarativeness that come down to individual judgment calls. These are some of the factors to be considered:

I would change this to

This is because JSX, just like JavaScript, requires frequent compromises between readability and declarativeness that come down to individual judgment calls. These are some of the factors to be considered:

Contributor

gaearon commented Aug 16, 2016

This is because JSX requires frequent compromises between readability and declarativeness that come down to individual judgment calls. These are some of the factors to be considered:

I would change this to

This is because JSX, just like JavaScript, requires frequent compromises between readability and declarativeness that come down to individual judgment calls. These are some of the factors to be considered:

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 16, 2016

Contributor

To address the above two concerns, many choose to do as much as possible outside JSX, then only embed a variable, like children in the example above. The downside is that the render function then ceases to be a declarative description of the generated view, instead becoming an imperative list of operations with a final result.

I would add that the common solution is to extract functions (or more components), just like in JavaScript. It鈥檚 not a problem unique to UI at all.

Contributor

gaearon commented Aug 16, 2016

To address the above two concerns, many choose to do as much as possible outside JSX, then only embed a variable, like children in the example above. The downside is that the render function then ceases to be a declarative description of the generated view, instead becoming an imperative list of operations with a final result.

I would add that the common solution is to extract functions (or more components), just like in JavaScript. It鈥檚 not a problem unique to UI at all.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 16, 2016

Contributor

The downside is that the render function then ceases to be a declarative description of the generated view

I would not agree with that statement. It is still declarative because its result describes the UI. Whether you use map or push, ternary of if, to produce this result, is an irrelevant implementation detail.

Contributor

gaearon commented Aug 16, 2016

The downside is that the render function then ceases to be a declarative description of the generated view

I would not agree with that statement. It is still declarative because its result describes the UI. Whether you use map or push, ternary of if, to produce this result, is an irrelevant implementation detail.

@blocka

This comment has been minimized.

Show comment
Hide comment
@blocka

blocka Aug 17, 2016

I would like to add one point, that I think has not been mentioned. React, in general, is more "friendly" to functional programming paradigms. It embraces concepts like immutability, for example, and there are plenty of articles about using React in more functional terms. Vue, relies on mutability, however, which is not inline with functional programming. If somebody wanted to use redux with vue, they are at a serious disadvantage as there are no hooks to prevent unnecessary re-renders (componentWillUpdate).

So bottom line, if enjoy functional programming, or "functional style" programming, react offers a lot more for you.

If you don't care much for that paradigm, then vue offers a lot.

blocka commented Aug 17, 2016

I would like to add one point, that I think has not been mentioned. React, in general, is more "friendly" to functional programming paradigms. It embraces concepts like immutability, for example, and there are plenty of articles about using React in more functional terms. Vue, relies on mutability, however, which is not inline with functional programming. If somebody wanted to use redux with vue, they are at a serious disadvantage as there are no hooks to prevent unnecessary re-renders (componentWillUpdate).

So bottom line, if enjoy functional programming, or "functional style" programming, react offers a lot more for you.

If you don't care much for that paradigm, then vue offers a lot.

@yyx990803

This comment has been minimized.

Show comment
Hide comment
@yyx990803

yyx990803 Aug 17, 2016

Member

@blocka fyi using Redux with Vue doesn't entail too much unnecessary re-renders, because Redux reducers simulate structural sharing to some extent, and any part of the state tree that retains old references will not trigger any re-render. There's also the opportunity to perform optimization in the component connectors, similar to that in react-redux, which makes shouldComponentUpdate unnecessary.

I'd agree React is in general more functional-friendly, but it's more of a design philosophy / ecosystem thing rather than technical advantage/disadvantages.

Member

yyx990803 commented Aug 17, 2016

@blocka fyi using Redux with Vue doesn't entail too much unnecessary re-renders, because Redux reducers simulate structural sharing to some extent, and any part of the state tree that retains old references will not trigger any re-render. There's also the opportunity to perform optimization in the component connectors, similar to that in react-redux, which makes shouldComponentUpdate unnecessary.

I'd agree React is in general more functional-friendly, but it's more of a design philosophy / ecosystem thing rather than technical advantage/disadvantages.

@blocka

This comment has been minimized.

Show comment
Hide comment
@blocka

blocka Aug 17, 2016

The comparison is not just, or should not be just, about technical advantages...but also philosophy. Ecosystem is also a huge thing when deciding what library to use.

I was under the impression that the reducers work top down and replace the state on every action (I actually don't have much practical usage of redux, just pretty well read up.

I'm sure both of us don't want this thread to get too out of hand, but can I ask you to elaborate on the statement "There's also the opportunity to perform optimization in the component connectors"?

blocka commented Aug 17, 2016

The comparison is not just, or should not be just, about technical advantages...but also philosophy. Ecosystem is also a huge thing when deciding what library to use.

I was under the impression that the reducers work top down and replace the state on every action (I actually don't have much practical usage of redux, just pretty well read up.

I'm sure both of us don't want this thread to get too out of hand, but can I ask you to elaborate on the statement "There's also the opportunity to perform optimization in the component connectors"?

@yyx990803

This comment has been minimized.

Show comment
Hide comment
@yyx990803

yyx990803 Aug 17, 2016

Member

@blocka we obviously can mention the philosophical differences, I was just pointing out that the technical assumptions in your comment was inaccurate.

When you return a new state object in a reducer in the form of { ...oldState, changedField: value }, any field other than changedField are copied into the new state object, and still retains the old reference. To Vue, this means any non-container components that receive the exact same props will not re-render (consider shouldComponentUpdate already implemented for you).

When you connect state from the Redux store into a container component, you essentially add a subscribe callback to the store, in which you reduce the whole state tree to the subset that the connected component is interested in before triggering component re-render. This is what the connect function in react-redux does. During this process there is the opportunity to do a shallow compare of the reduced state - if everything remains the same you can skip the re-render.

So technically you can achieve very efficient updates when using Redux and Vue without using something like shouldComponentUpdate.

Member

yyx990803 commented Aug 17, 2016

@blocka we obviously can mention the philosophical differences, I was just pointing out that the technical assumptions in your comment was inaccurate.

When you return a new state object in a reducer in the form of { ...oldState, changedField: value }, any field other than changedField are copied into the new state object, and still retains the old reference. To Vue, this means any non-container components that receive the exact same props will not re-render (consider shouldComponentUpdate already implemented for you).

When you connect state from the Redux store into a container component, you essentially add a subscribe callback to the store, in which you reduce the whole state tree to the subset that the connected component is interested in before triggering component re-render. This is what the connect function in react-redux does. During this process there is the opportunity to do a shallow compare of the reduced state - if everything remains the same you can skip the re-render.

So technically you can achieve very efficient updates when using Redux and Vue without using something like shouldComponentUpdate.

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Aug 17, 2016

Member

@gaearon Just made the updates you suggested. Then regarding a couple other items:

Defining declarativeness

I would not agree with that statement. It is still declarative because its result describes the UI. Whether you use map or push, ternary of if, to produce this result, is an irrelevant implementation detail.

With the definitions I'm familiar with, mutation within the function makes it imperative rather than declarative. I agree that the final return statement is declarative and I've updated to make that more clear. Let me know if the new language makes sense to you.

Just noticed a missing ul in React example

So I just updated this:

children = items.map(item =>
  <li key={item.id}>{item.name}</li>
)

to:

children = (
  <ul>
    {items.map(item =>
      <li key={item.id}>{item.name}</li>
    )}
  </ul>
)

If that doesn't match your preferred style though, I'm happy to update. 馃槂

Member

chrisvfritz commented Aug 17, 2016

@gaearon Just made the updates you suggested. Then regarding a couple other items:

Defining declarativeness

I would not agree with that statement. It is still declarative because its result describes the UI. Whether you use map or push, ternary of if, to produce this result, is an irrelevant implementation detail.

With the definitions I'm familiar with, mutation within the function makes it imperative rather than declarative. I agree that the final return statement is declarative and I've updated to make that more clear. Let me know if the new language makes sense to you.

Just noticed a missing ul in React example

So I just updated this:

children = items.map(item =>
  <li key={item.id}>{item.name}</li>
)

to:

children = (
  <ul>
    {items.map(item =>
      <li key={item.id}>{item.name}</li>
    )}
  </ul>
)

If that doesn't match your preferred style though, I'm happy to update. 馃槂

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 17, 2016

Contributor

With the definitions I'm familiar with, mutation within the function makes it imperative rather than declarative. I agree that the final return statement is declarative and I've updated to make that more clear. Let me know if the new language makes sense to you.

I think when people talk about imperative vs declarative UI, they talk about intent in a wider model. In React鈥檚 case, elements describe resulting component trees. This is why it is called declarative. Not because your code doesn鈥檛 use let or if statements. This is actually rather wrong鈥攁 function can be pure and still use them just fine as long as it doesn鈥檛 have any side effects or doesn鈥檛 cause any external mutations. Local variables don鈥檛 count: they are implementation details, and aren鈥檛 part of the function contract.

How you put items in array of those elements, or where you assign a variable value, has very little to do with the paradigm. It has zero observable effects and exactly the same semantics. I don鈥檛 want to make a big argument about it in case you disagree, but I find it weird to put any accent on this.

Contributor

gaearon commented Aug 17, 2016

With the definitions I'm familiar with, mutation within the function makes it imperative rather than declarative. I agree that the final return statement is declarative and I've updated to make that more clear. Let me know if the new language makes sense to you.

I think when people talk about imperative vs declarative UI, they talk about intent in a wider model. In React鈥檚 case, elements describe resulting component trees. This is why it is called declarative. Not because your code doesn鈥檛 use let or if statements. This is actually rather wrong鈥攁 function can be pure and still use them just fine as long as it doesn鈥檛 have any side effects or doesn鈥檛 cause any external mutations. Local variables don鈥檛 count: they are implementation details, and aren鈥檛 part of the function contract.

How you put items in array of those elements, or where you assign a variable value, has very little to do with the paradigm. It has zero observable effects and exactly the same semantics. I don鈥檛 want to make a big argument about it in case you disagree, but I find it weird to put any accent on this.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 17, 2016

Contributor

I would rewrite

To address the above two concerns, the simplest option is to do as much as possible outside JSX, then only embed a variable, like children in the example above. The downside is that the render function then ceases to be a purely declarative description of the generated view, instead becoming an imperative list of operations with a declarative (but less descriptive) result.

as

To address the above two concerns, the simplest option is to do as much as possible outside JSX, then only embed a variable, like children in the example above. The downside is that now you have to keep track of what these variables are assigned to, just like in regular JavaScript functions.

The part about 鈥渋mperative list of operations鈥 and 鈥渄eclarative (but less descriptive) result鈥 seems very off to me. Beginners will think React somehow stops being declarative if you use if or let (no it doesn鈥檛). Whether result is 鈥渄escriptive鈥 is completely subjective.

Contributor

gaearon commented Aug 17, 2016

I would rewrite

To address the above two concerns, the simplest option is to do as much as possible outside JSX, then only embed a variable, like children in the example above. The downside is that the render function then ceases to be a purely declarative description of the generated view, instead becoming an imperative list of operations with a declarative (but less descriptive) result.

as

To address the above two concerns, the simplest option is to do as much as possible outside JSX, then only embed a variable, like children in the example above. The downside is that now you have to keep track of what these variables are assigned to, just like in regular JavaScript functions.

The part about 鈥渋mperative list of operations鈥 and 鈥渄eclarative (but less descriptive) result鈥 seems very off to me. Beginners will think React somehow stops being declarative if you use if or let (no it doesn鈥檛). Whether result is 鈥渄escriptive鈥 is completely subjective.

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Aug 18, 2016

Member

@gaearon I definitely wasn't trying to imply an effect on the declarativeness of the overall UI paradigm or the purity of the render function, but just speaking of declarative/imperative programming styles. I can definitely see your point though, that the distinction may be unclear to beginners.

Thinking about it more, this entire section has grown far beyond what we originally intended. We're more interested in just showing off what makes templates great and I think we can do that without the deeper dive into the render function, so I've just deleted it. Let me know if that resolves your concerns.

Member

chrisvfritz commented Aug 18, 2016

@gaearon I definitely wasn't trying to imply an effect on the declarativeness of the overall UI paradigm or the purity of the render function, but just speaking of declarative/imperative programming styles. I can definitely see your point though, that the distinction may be unclear to beginners.

Thinking about it more, this entire section has grown far beyond what we originally intended. We're more interested in just showing off what makes templates great and I think we can do that without the deeper dive into the render function, so I've just deleted it. Let me know if that resolves your concerns.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 18, 2016

Contributor

Looks great 馃憤

Contributor

gaearon commented Aug 18, 2016

Looks great 馃憤

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Aug 18, 2016

Member

So bottom line, if enjoy functional programming, or "functional style" programming, react offers a lot more for you.

If you don't care much for that paradigm, then vue offers a lot.

@blocka I'd like to add a little more to explain why this is the wrong way to think about it.

First, it's important to note that functional paradigms are a means, not an end. Colleagues of mine would certainly report that I "enjoy functional programming", but what I actually enjoy is code that is simple to reason about and produces extremely few bugs. A functional programming style is one tool that often helps me achieve this. In Vue, I have never missed immutable data, because it's made unnecessary by enhancing mutable data with automatic dependency tracking. This allows me to write:

this.todos.push(this.newTodo)

Then the UI and other computed data will automatically update accordingly - and very efficiently. I don't have to worry about state bugs or side effects and it's very clear what this code does. React, on the other hand, handles the state problem in a technically more functional way by forcing all updates to go through setState and encouraging the creation of new objects:

this.setState({ todos: todos.concat(this.state.newTodo) })

This is not only more verbose, but also slower. First, concat is less performant than push. Then without a custom shouldComponentUpdate function there's also no smart dependency-tracking, so re-renders will happen whether they need to or not. However, if we do add custom shouldComponentUpdate functions and incorporate immutable data structures using ImmutableJS:

this.setState(({data}) => ({
  data: data.update('todos', list => list.push(data.get('newTodo')))
}))

Then we can finally come close to the efficiency of Vue out-of-the-box. But at what cost? Being more "functional" in this case has made our code more time-consuming to write and more difficult to read. So Vue's reactivity system actually achieves the ends of immutable data better than immutable data itself - at least within the context of JavaScript, where immutability is far from a first-class citizen.

Member

chrisvfritz commented Aug 18, 2016

So bottom line, if enjoy functional programming, or "functional style" programming, react offers a lot more for you.

If you don't care much for that paradigm, then vue offers a lot.

@blocka I'd like to add a little more to explain why this is the wrong way to think about it.

First, it's important to note that functional paradigms are a means, not an end. Colleagues of mine would certainly report that I "enjoy functional programming", but what I actually enjoy is code that is simple to reason about and produces extremely few bugs. A functional programming style is one tool that often helps me achieve this. In Vue, I have never missed immutable data, because it's made unnecessary by enhancing mutable data with automatic dependency tracking. This allows me to write:

this.todos.push(this.newTodo)

Then the UI and other computed data will automatically update accordingly - and very efficiently. I don't have to worry about state bugs or side effects and it's very clear what this code does. React, on the other hand, handles the state problem in a technically more functional way by forcing all updates to go through setState and encouraging the creation of new objects:

this.setState({ todos: todos.concat(this.state.newTodo) })

This is not only more verbose, but also slower. First, concat is less performant than push. Then without a custom shouldComponentUpdate function there's also no smart dependency-tracking, so re-renders will happen whether they need to or not. However, if we do add custom shouldComponentUpdate functions and incorporate immutable data structures using ImmutableJS:

this.setState(({data}) => ({
  data: data.update('todos', list => list.push(data.get('newTodo')))
}))

Then we can finally come close to the efficiency of Vue out-of-the-box. But at what cost? Being more "functional" in this case has made our code more time-consuming to write and more difficult to read. So Vue's reactivity system actually achieves the ends of immutable data better than immutable data itself - at least within the context of JavaScript, where immutability is far from a first-class citizen.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 18, 2016

Contributor

I don't see

return n < 2 ?
  n :
  fib(n - 1) + fib(n - 2)

as any more declarative than

result = n
if n > 1
  a = fib(n - 1)
  b = fib(n - 2)
  result = a +b
return result

You don't lose any properties of the declarative system if you start to use if statements or vars.

If you never reassign variables the point is even mooter. Otherwise it seems like you suggest that the only way to keep things declarative is to never give names to them.

Maybe my point will be a little more clear if you imagine numbers I nstead of JSX. It would seem strange that using ternary operator somehow makes number operations declarative, and using if statements somehow makes the exact same operations imperative.

(And yes, I'd love to have an if expression in JavaScript but we are all aware of the language we are dealing with so let's not be purists 馃槈 )

Contributor

gaearon commented Aug 18, 2016

I don't see

return n < 2 ?
  n :
  fib(n - 1) + fib(n - 2)

as any more declarative than

result = n
if n > 1
  a = fib(n - 1)
  b = fib(n - 2)
  result = a +b
return result

You don't lose any properties of the declarative system if you start to use if statements or vars.

If you never reassign variables the point is even mooter. Otherwise it seems like you suggest that the only way to keep things declarative is to never give names to them.

Maybe my point will be a little more clear if you imagine numbers I nstead of JSX. It would seem strange that using ternary operator somehow makes number operations declarative, and using if statements somehow makes the exact same operations imperative.

(And yes, I'd love to have an if expression in JavaScript but we are all aware of the language we are dealing with so let's not be purists 馃槈 )

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Aug 18, 2016

Member

@gaearon It sounds like we may simply be working off different definitions. 炉\_(銉)_/炉

Without using the words declarative or imperative, what I was referring to was the additional complexity and cognitive overhead of writing and reading code that tells a story, in comparison to code that describes a law.

Code that tells a story requires describing how we arrive at a value (i.e implementation details), which means implementation decisions. Then later, we have to walk ourselves through that story and keep it all in our heads as we do, because each line might change how lines below it evaluate - there's a whole new dimension we have to think about: time. For the example you provided:

return n < 2 ?
  n :
  fib(n - 1) + fib(n - 2)

Understanding when/how lines 2 and 3 are evaluated depend on line 1. It's relatively low in complexity, because to understand it, we need only concern ourselves with a single moment in time. In the version that tells a story:

result = n
if n > 1
  a = fib(n - 1)
  b = fib(n - 2)
  result = a +b
return result

Line 6 depends on lines 1 and 5, which depends on line 2 to know if it's evaluated at all, then if it is, on lines 3 and 4 to know what we're adding together.

Both examples are equivalent in terms of function purity, so the larger application is not polluted or otherwise affected, but one is definitely more complex (and therefore more difficult to read, modify, and debug) than the other. I agree that this is inevitable in render functions though, due to inherent limitations in JavaScript. It's certainly not due to any flaw in React, as the same compromises have to be made using Vue's render functions.

Member

chrisvfritz commented Aug 18, 2016

@gaearon It sounds like we may simply be working off different definitions. 炉\_(銉)_/炉

Without using the words declarative or imperative, what I was referring to was the additional complexity and cognitive overhead of writing and reading code that tells a story, in comparison to code that describes a law.

Code that tells a story requires describing how we arrive at a value (i.e implementation details), which means implementation decisions. Then later, we have to walk ourselves through that story and keep it all in our heads as we do, because each line might change how lines below it evaluate - there's a whole new dimension we have to think about: time. For the example you provided:

return n < 2 ?
  n :
  fib(n - 1) + fib(n - 2)

Understanding when/how lines 2 and 3 are evaluated depend on line 1. It's relatively low in complexity, because to understand it, we need only concern ourselves with a single moment in time. In the version that tells a story:

result = n
if n > 1
  a = fib(n - 1)
  b = fib(n - 2)
  result = a +b
return result

Line 6 depends on lines 1 and 5, which depends on line 2 to know if it's evaluated at all, then if it is, on lines 3 and 4 to know what we're adding together.

Both examples are equivalent in terms of function purity, so the larger application is not polluted or otherwise affected, but one is definitely more complex (and therefore more difficult to read, modify, and debug) than the other. I agree that this is inevitable in render functions though, due to inherent limitations in JavaScript. It's certainly not due to any flaw in React, as the same compromises have to be made using Vue's render functions.

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Aug 24, 2016

Member

@gaearon For the render performance section, I ended up going even simpler than a visualization demo, in order to demonstrate render performance more purely (outside the context of updates). If there's anything in the React examples that makes the comparisons unfair, please do let me know!

I also tried to make it clearer that what we're comparing is overhead over the minimal required work to render the UI, since neither Vue nor React can make individual DOM manipulations any faster. That seemed to be unclear to some readers previously.

Member

chrisvfritz commented Aug 24, 2016

@gaearon For the render performance section, I ended up going even simpler than a visualization demo, in order to demonstrate render performance more purely (outside the context of updates). If there's anything in the React examples that makes the comparisons unfair, please do let me know!

I also tried to make it clearer that what we're comparing is overhead over the minimal required work to render the UI, since neither Vue nor React can make individual DOM manipulations any faster. That seemed to be unclear to some readers previously.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 25, 2016

Contributor

There are a few reasons why I think the benchmark is still a little problematic:

  • JSFiddle is not a realistic environment. I would prefer to see a comparison done with a real production-ready setup, like what Create React App produces on npm run build (and a similar Vue template, respectively).
  • Measuring start time of both React.createClass and ReactDOM.render() seems a little unfair because Vue example doesn鈥檛 seem to differentiate class declaration and rendering operation. It鈥檚 known that React.createClass() takes more time to initialize, which is the reason we鈥檙e encouraging people to use ES6 classes (or functional components) instead.
  • It鈥檚 also not clear to me why Vue example uses a variable but React example uses component state. I鈥檓 not saying it makes a difference, but it was a bit weird in such a small comparison.
  • It would be great to make measurements after a warmup. In real apps, there are more components than a single component with a thousands of rows. We don鈥檛 optimize the code for 鈥渏sfiddle benchmark鈥 use case. So I would recommend creating a hierarchy of components (2 or 3 levels), changing both examples to mount those instead, and making a few passes before taking the measurements.
Contributor

gaearon commented Aug 25, 2016

There are a few reasons why I think the benchmark is still a little problematic:

  • JSFiddle is not a realistic environment. I would prefer to see a comparison done with a real production-ready setup, like what Create React App produces on npm run build (and a similar Vue template, respectively).
  • Measuring start time of both React.createClass and ReactDOM.render() seems a little unfair because Vue example doesn鈥檛 seem to differentiate class declaration and rendering operation. It鈥檚 known that React.createClass() takes more time to initialize, which is the reason we鈥檙e encouraging people to use ES6 classes (or functional components) instead.
  • It鈥檚 also not clear to me why Vue example uses a variable but React example uses component state. I鈥檓 not saying it makes a difference, but it was a bit weird in such a small comparison.
  • It would be great to make measurements after a warmup. In real apps, there are more components than a single component with a thousands of rows. We don鈥檛 optimize the code for 鈥渏sfiddle benchmark鈥 use case. So I would recommend creating a hierarchy of components (2 or 3 levels), changing both examples to mount those instead, and making a few passes before taking the measurements.
@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Aug 26, 2016

Member

@gaearon Thanks for taking a look! The variable in the Vue example was a typo. 馃槄 To address the other items, I'll take some time this weekend to write a pair of benchmark apps.

Member

chrisvfritz commented Aug 26, 2016

@gaearon Thanks for taking a look! The variable in the Vue example was a typo. 馃槄 To address the other items, I'll take some time this weekend to write a pair of benchmark apps.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Aug 26, 2016

Contributor

Thanks!

Contributor

gaearon commented Aug 26, 2016

Thanks!

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Aug 29, 2016

Member

@gaearon Alright, here are those benchmark apps and some revised copy to go along with them. As always, thoughts/PRs are very welcome! 馃槃

Member

chrisvfritz commented Aug 29, 2016

@gaearon Alright, here are those benchmark apps and some revised copy to go along with them. As always, thoughts/PRs are very welcome! 馃槃

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Sep 3, 2016

Member

Hey @gaearon, just pinging on this. If you have time, we're thinking of officially publishing the 2.0 docs soon and want to make sure we're not spreading misinformation by mistake! I've also tried to better emphasize the benefits of render functions and JSX, so if you happen to think of something I've missed, let me know and I'll add it to the list.

Member

chrisvfritz commented Sep 3, 2016

Hey @gaearon, just pinging on this. If you have time, we're thinking of officially publishing the 2.0 docs soon and want to make sure we're not spreading misinformation by mistake! I've also tried to better emphasize the benefits of render functions and JSX, so if you happen to think of something I've missed, let me know and I'll add it to the list.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Sep 3, 2016

Contributor

This is great, thank you so much for doing it. 馃憤
Sorry I missed your comment earlier.

Contributor

gaearon commented Sep 3, 2016

This is great, thank you so much for doing it. 馃憤
Sorry I missed your comment earlier.

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Sep 4, 2016

Member

Excellent! I'll close this issue for now then, but happy to reopen if something else catches your eye.

Member

chrisvfritz commented Sep 4, 2016

Excellent! I'll close this issue for now then, but happy to reopen if something else catches your eye.

@chrisvfritz chrisvfritz closed this Sep 4, 2016

@51mon

This comment has been minimized.

Show comment
Hide comment
@51mon

51mon Oct 8, 2016

What's the point of having a children variable into the JSX code ?
It would be simpler to have the if / else statement directly inside the return.

51mon commented Oct 8, 2016

What's the point of having a children variable into the JSX code ?
It would be simpler to have the if / else statement directly inside the return.

@chrisvfritz

This comment has been minimized.

Show comment
Hide comment
@chrisvfritz

chrisvfritz Oct 8, 2016

Member

@51mon We could endlessly bikeshed this example, arguing about style preferences. Many people find this version of the code more natural. Some will not. It was provided by Dan Abramov though, so it will be similar in style to doc examples people see throughout the React community.

Member

chrisvfritz commented Oct 8, 2016

@51mon We could endlessly bikeshed this example, arguing about style preferences. Many people find this version of the code more natural. Some will not. It was provided by Dan Abramov though, so it will be similar in style to doc examples people see throughout the React community.

kazupon added a commit to kazupon/vuejs.org that referenced this issue Nov 24, 2017

Update syntax section (#364)
* pick up from commit

NOTE:
  ref: vuejs@8f55bb0

* translate prev commit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment