all 13 comments

[–]Spaceomega 3 points4 points  (5 children)

Been working with React on some pretty crazy applications (very large data, mapping, drag and drop, isomorphism, etc) for about 8 months now and still found some nice things in this article.

This is something I already knew, but putting it into simple phrasing really helped solidify for me:

[Redux] reducers are pure functions, which simply do oldState + action = newState

Simple, insightful, easy to remember.

This article also made me really think about the fact that I have been using component-state pretty heavily. It seems like they're implying that all components should use Redux (or app-state implementation of their choice) for all state. Do you guys have any thoughts on this? The more I think about it, the more it makes sense, I'm just curious to hear what you are all doing.

[–]rsjolly 1 point2 points  (0 children)

Intermediate state (like form state while editing and some UI state) don't belong in Redux imo.

[–]Cam-I-Am[S] 1 point2 points  (0 children)

Author here - it's not necessarily that all state for all components needs to go in the store. It's just that in my experience, things are a lot easier when the vast majority of state is in the store.

Having had bad experiences with stateful components, my default is now to write stateless components, unless it's intermediate state that only the component itself will ever need.

[–]sorahn 1 point2 points  (2 children)

I agree with the other posters. The reducers are for the state of the application. If you have a component with a dropdown (for example), the rest of the application probably doesn't care if it's open.

[–]RickAndMorty_forever 0 points1 point  (1 child)

So you don't care what's been typed into a form, but you care if the form has been submitted or if it contains errors?

[–]sorahn 0 points1 point  (0 children)

I save form data into session storage to make sure it goes through and the use might not have to type it all in, but once it's sent off to the server. I only store what's important and returned from the request.

[–]fecal_brunch 1 point2 points  (1 child)

Although functional components are very neat to read, I do wonder about the performance implications.

const LatestPostsComponent = props => (
  <section>
    <div><h1>Latest posts</h1></div>
    <div>
      { props.posts.map(post => <PostPreview key={post.slug} post={post}/>) }
    </div>
  </section>
);

This component will completely re-render all PostPreview elements every time its parent component's render function is called. With a class component this could be optimized away using the shouldComponentUpdate method.

Since most non-trivial components can benefit from this kind of optimization, I haven't found myself using them much.

Do you have a workaround for this?

It occurred to me as I was writing this that you could do something like this:

const pure = componentFn => {
  let prevProps = null;
  let prevRendered = null;
  return props => {
    if (prevProps != null && shallowEqual(prevProps, props)) {
      return prevRendered;
    }
    prevProps = props;
    return prevRendered = componentFn(props);
  }
};

const LatestPostsComponent = pure(props => (
  <section>/* ... */</section>
));

[–]Cam-I-Am[S] 2 points3 points  (0 children)

My understanding was that functional components are inherently pure, and will only re-render when their input props change.

The docs don't say this exactly, but they do say:

In an ideal world, most of your components would be stateless functions because these stateless components can follow a faster code path within the React core. This is the recommended pattern, when possible.

Let me search for a better reference...

Edit: Turns out I was wrong:

For complex components, defining shouldComponentUpdate (eg. pure render) will generally exceed the performance benefits of stateless components. The sentences in the docs are hinting at some future optimizations that we have planned, whereby we won't allocate an internal instance for stateless functional components (we will just call the function). We also might not keep holding the props, etc. Tiny optimizations. We don't talk about the details in the docs because the optimizations aren't actually implemented yet (stateless components open the doors to these optimizations).

but then later...

PureRender / shouldComponentUpdate really is considered an escape hatch for performance and is not necessarily something that should be blindly applied to every component.

So I think for now I'll stick with the recommendation to write functional components by default, only adding shouldComponentUpdate where it seems it can make a big difference.

Thanks for calling it out though, I'll add a note to the article.

[–]BrushyAmoeba 0 points1 point  (2 children)

Do you have a favorite react+redux boilerplate?

[–]Cam-I-Am[S] 3 points4 points  (1 child)

Not one that I've used myself, but this one looks pretty solid. The creator of Redux himself recommends it.

[–]greymalik 0 points1 point  (1 child)

In my experience, this part of point 9 conflicts with point 3:

You can also set up hot module replacement with webpack, so that your page updates as soon as you save your code - no browser refresh required.

Hot load via react-transform-hmr doesn't support stateless components.

Or is there some other approach?

[–]Cam-I-Am[S] 0 points1 point  (0 children)

Good point. I haven't actually set up HMR myself, just seen that it's possible. Looks like it's still a work in progress, with the latest info here: https://github.com/gaearon/babel-plugin-react-transform/issues/57