Live data from Hacker News

React Implementation Notes

facebook.github.io

71–80 of 93 posts

Re: React Implementation Notes

#71
post #57
post #24

Earlier quoted context omitted.

> 4) "You might not need Redux"[3] For some older projects I found a hand-built flux helper[0] of ~220 lines worked great and didn't require any toolchain modifications. The switching costs to some of the ES6 stuff was too high in that case, but it's also a potentially leaner app if you don't need the advanced features of Redux and ES6. The Redux architecture is so nice though. [0] https://github.com/guscost/simple-f…

I think redux got 50% right and 50% wrong. 1. good: having a sideeffect-free, serializable application state. That concept can also be used in mobile apps for easy pause/resume. 2. good: being able to render that state from one parent, because you don't need to manage two separate statemachines (the UI and the business logic) anymore. 3. bad: shoe-horning all state-transition into functions/reducers. Fp is awesome, b…

Um, no, you don't need to use Immutable with Redux. And regarding syntax, with object rest/spread (stage 3):

    (state, newName) => ({
       ...state,
       name: newName
    })
It's not that verbose.

Re: React Implementation Notes

#72

Earlier quoted context omitted.

FWIW we are trying to avoid "virtual DOM" in the new docs. The thing you create in render() and that describes the tree has been called "a React element" for many versions by now. "Virtual DOM" was more of a marketing term and I find it misleading because it doesn't make sense with e.g. React Native, and also makes React seem like a performance trick. React is not a performance trick. That elements get compared by Re…

> "React is abstraction for dividing UI into predictable pieces, not a performance optimization." Why can't it be both?

Performance is baseline. If something isn't performant we won't use it. But that's not the point of React.

React wouldn't exist if it wasn't performant. But the reason React exists is not performance.

Re: React Implementation Notes

#73
post #36

Earlier quoted context omitted.

What about generators? I've built coroutines based on generators. CSP has been implemented in JS using generators. Not sure why those projects went thru "staggering amount of overhead" to get what we get for free with generators. Please educate.

The main difference is that all of the use cases I mentioned necessarily don't distinguish between calls/functions that may pause, and calls that don't (it's just the semantics of those languages that arbitrary calls might need to pause). So to use generators as a compilation target, every function has to be a generator, and every call a generator instantiation followed by yield*. I actually don't know if that qualif…

>

Sure, but in those cases the functions are transpiled to JS so it doesn't really matter, not like they're coded by hand, right...? I think I understand what you mean.

Re: React Implementation Notes

#74
post #57
post #24

Earlier quoted context omitted.

> 4) "You might not need Redux"[3] For some older projects I found a hand-built flux helper[0] of ~220 lines worked great and didn't require any toolchain modifications. The switching costs to some of the ES6 stuff was too high in that case, but it's also a potentially leaner app if you don't need the advanced features of Redux and ES6. The Redux architecture is so nice though. [0] https://github.com/guscost/simple-f…

I think redux got 50% right and 50% wrong. 1. good: having a sideeffect-free, serializable application state. That concept can also be used in mobile apps for easy pause/resume. 2. good: being able to render that state from one parent, because you don't need to manage two separate statemachines (the UI and the business logic) anymore. 3. bad: shoe-horning all state-transition into functions/reducers. Fp is awesome, b…

My main hesitation with Redux is how awkward it is to insert async calls in the chain of events. Things like redux-thunk and redux-saga are impressive hacks but feel like a lot of gymnastics to do something that pretty much every React app needs to do.

Re: React Implementation Notes

#75

I'm a Rails developer. I work on pretty standard web apps for a living. Some more complicated than others, but still, web apps. I still haven't found a person that was able to give me a concrete reason why someone like me should invest time and resources into learning React and using it in my projects. This is an honest question, I'm not trying to be sarcastic. It's just that there are so many frameworks that come ou…

I gave a talk on this few weeks ago; The slides can be found here: https://react-redux-presentation.herokuapp.com/

Hope it helps

Re: React Implementation Notes

#76
post #57
post #24

Earlier quoted context omitted.

> 4) "You might not need Redux"[3] For some older projects I found a hand-built flux helper[0] of ~220 lines worked great and didn't require any toolchain modifications. The switching costs to some of the ES6 stuff was too high in that case, but it's also a potentially leaner app if you don't need the advanced features of Redux and ES6. The Redux architecture is so nice though. [0] https://github.com/guscost/simple-f…

I think redux got 50% right and 50% wrong. 1. good: having a sideeffect-free, serializable application state. That concept can also be used in mobile apps for easy pause/resume. 2. good: being able to render that state from one parent, because you don't need to manage two separate statemachines (the UI and the business logic) anymore. 3. bad: shoe-horning all state-transition into functions/reducers. Fp is awesome, b…

You don't need to use Immutable.js (I never do) but making your state immutable/functional is what makes the magic work. You don't have to worry about observing data or manually handling data updates -- everything just works. Compare this to MobX where there's an explicit pubsub model. In my opinion that works best for small apps, but falls apart in large ones (where Redux shines).

Re: React Implementation Notes

#77
post #36

Earlier quoted context omitted.

The main difference is that all of the use cases I mentioned necessarily don't distinguish between calls/functions that may pause, and calls that don't (it's just the semantics of those languages that arbitrary calls might need to pause). So to use generators as a compilation target, every function has to be a generator, and every call a generator instantiation followed by yield*. I actually don't know if that qualif…

> Sure, but in those cases the functions are transpiled to JS so it doesn't really matter, not like they're coded by hand, right...? I think I understand what you mean.

I don't know what you mean by "it doesn't really matter." Surely there's a cost to using generators instead of regular function calls and returns, right? That's where the overhead would come from, because generators aren't free.

Right now, Pyret and GopherJS (the last time I checked in GopherJS's case) basically manually encode the `IteratorResult` type, and check for "stack unwind" vs "regular result" when each function call returns, if it might pause.

The first question for generators is if they are less overhead than this manual process. There's a bunch of other details, too, but this is the main one. And generators are certainly going to cause _some_ overhead over regular calls and returns, just like the manual checking of return values has overhead.

My original comment was about the lack of something like delimited continuations in JS, which would allow saving portions of the stack while intentionally minimizing the overhead of regular function calls. That's a well-fitting language-level solution to this issue.

Re: React Implementation Notes

#78
post #68
post #67

Earlier quoted context omitted.

Unless something has changed very recently, you don't have to use Immutable.js and redux together. Redux advises against mutating your state, but doesn't prescribe a way to do that.

True, I did applications with redux and without immutable too, even wrote my own syntax magic for that: https://www.npmjs.com/package/babel-plugin-check-data-access What redux misses as well are derived/computed properties, I think mobX has them: https://mobxjs.github.io/mobx/

The standard approach is to store the minimal amount of data directly in the state, and derive data as needed externally to the store. This is usually done with "selector functions". See http://redux.js.org/docs/recipes/ComputingDerivedData.html , https://medium.com/@adamrackis/querying-a-redux-store-37db8c... , and http://redux.js.org/docs/faq/CodeStructure.html#structure-fi... for more information.

Re: React Implementation Notes

#79
post #57
post #24

Earlier quoted context omitted.

> 4) "You might not need Redux"[3] For some older projects I found a hand-built flux helper[0] of ~220 lines worked great and didn't require any toolchain modifications. The switching costs to some of the ES6 stuff was too high in that case, but it's also a potentially leaner app if you don't need the advanced features of Redux and ES6. The Redux architecture is so nice though. [0] https://github.com/guscost/simple-f…

I think redux got 50% right and 50% wrong. 1. good: having a sideeffect-free, serializable application state. That concept can also be used in mobile apps for easy pause/resume. 2. good: being able to render that state from one parent, because you don't need to manage two separate statemachines (the UI and the business logic) anymore. 3. bad: shoe-horning all state-transition into functions/reducers. Fp is awesome, b…

2. good: being able to render that state from one parent, because you don't need to manage two separate statemachines (the UI and the business logic) anymore.

This is one of the areas I found to be most disappointing in practice about using a data store built with an immutable state tree and then using self-contained transactions to update it, which is similar to the Redux+Immutable model.

One of my current projects is a somewhat large web application. It has relatively complicated state to maintain for a web app, with very heterogeneous data and lots of relationships and constraints to enforce between data points.

In the early days, using React for rendering was quite convenient, and using Immutable then made writing shouldComponentUpdate quick and reliable, which was necessary almost immediately to achieve acceptable performance with React. Essentially, you’re using references within the immutable data as a proxy for a “dirty” flag on each part of your state.

However, it wasn’t long before the presentation code started to depend on derived state that was expensive to recompute: temporary tables, automatic diagram layouts, etc. This is where I find the immutable data structures really lose out compared to some sort of lazy observer architecture, because you are back to having a synchronisation problem between your derived view state and your underlying data model.

You can set up your derived view state as immutable values as well, and thus keep the reasonably simple shouldComponentUpdate mechanics, but you still need to either push changes from the underlying data model or pull them from the view. In the former case, you’ve effectively given up the declarative rendering that makes React more attractive than actively updating the DOM in the first place. In the latter case, you’ve created cache invalidation problems that undermine the benefits of having a cleanly updated, immutability-based data store in the first place.

There are several other advantages that have proved to be useful with this particular combination of tools, but they do come with some nasty performance and scalability implications, and in particular, they don’t generalise and compose cleanly in the way that a good observer-based design would. Worse, I suspect the difficulty of managing derived view state efficiently is inherent to this sort of architecture, because it seems almost inevitable in any system with data complicated enough that using a separate data store and declarative view rendering is worth the performance overheads in the first place.

Re: React Implementation Notes

#80
post #77

Earlier quoted context omitted.

> Sure, but in those cases the functions are transpiled to JS so it doesn't really matter, not like they're coded by hand, right...? I think I understand what you mean.

I don't know what you mean by "it doesn't really matter." Surely there's a cost to using generators instead of regular function calls and returns, right? That's where the overhead would come from, because generators aren't free. Right now, Pyret and GopherJS (the last time I checked in GopherJS's case) basically manually encode the `IteratorResult` type, and check for "stack unwind" vs "regular result" when each func…

Ah! You're right. Now I get what you mean. Thanks.
Post reply on HN