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

Dumb/smart component pattern and repaints #75

Closed
m4nuC opened this issue Aug 27, 2015 · 11 comments
Closed

Dumb/smart component pattern and repaints #75

m4nuC opened this issue Aug 27, 2015 · 11 comments

Comments

@m4nuC
Copy link

m4nuC commented Aug 27, 2015

Using the dumb/smart components pattern, does it mean that all dumb components will be re-rendered when the "containers" receive a new state notification ? For example in the the todo example adding a todo to the list will re-render the whole app.

Are there any pattern to optimise repaints in a larger app ?

@gnoff
Copy link
Contributor

gnoff commented Aug 27, 2015

React-Redux implements a pretty aggressive shouldComponentUpdate so state changes will only trigger re-renders if the slice of state @connect'd to results in a different set of state props (only checked shallowly)

That said. If the smart component does trigger a re-render and you are concerned about performance then you should implement shouldComponentUpdate in your 'dumb' components. In practice most components can use something like https://facebook.github.io/react/docs/pure-render-mixin.html

@gnoff gnoff closed this as completed Aug 27, 2015
@m4nuC
Copy link
Author

m4nuC commented Aug 27, 2015

I am not so much concerned about performance yet but I think many people are and that should be addressed in the docs.

As you said:

state changes will only trigger re-renders if the slice of state @connect'd to results in a different set of state props

In that case in the simple todo example form the doc, why would the footer component re-render when a todo is added? It doesn't share any state with the todo list.

@gnoff
Copy link
Contributor

gnoff commented Aug 27, 2015

This is a consequence of how React works, and react-redux actually improves the situation. In no way does connect cause there to be additional re-renders of the entire app tree that you wouldn't experience if you simply mutated a prop or state on a similarly positioned component.

That said, the footer in this example shows the todo count so it rightly does need to be re-rendered. but I believe that is beside your point.

bottom line is store subscriptions do not produce additional render noise as long as you are only subscribing to the slice of state the given component tree has an interest in reacting to.

@m4nuC
Copy link
Author

m4nuC commented Aug 27, 2015

That said, the footer in this example shows the todo count so it rightly does need to be re-rendered. but I believe that is beside your point.

Are we talking about the same example ?
image

This is a consequence of how React works, and react-redux actually improves the situation. In no way does connect cause there to be additional re-renders of the entire app tree that you wouldn't experience if you simply mutated a prop or state on a similarly positioned component.

My question is more about the dumb/smart component pattern. Is it correct to say that smart components re-render all their nested dumb components when state updates ? If so it's worth taking into account when structuring the app.

@gnoff
Copy link
Contributor

gnoff commented Aug 27, 2015

Are we talking about the same example ?

not sure, i'm talking about this here: https://github.com/rackt/redux/blob/master/examples/todomvc/components/Footer.js#L51

Is it correct to say that smart components re-render all their nested dumb components when state updates ? If so it's worth taking into account when structuring the app.

yes that's fair to say but I don't think it has a particularly deep implication for how one should structure their app.

@gaearon
Copy link
Contributor

gaearon commented Aug 27, 2015

Put connect() at the top until you hit performance problems, then put it somewhere in the middle to solve them.

@m4nuC
Copy link
Author

m4nuC commented Aug 27, 2015

Thanks, so one connect() at the top most level is the approach you'd recommend? It'd nice to have this statement in the docs somewhere, it'd help understanding the whole redux flow. Maybe a "flux like" diagram would help there as well.

then put it somewhere in the middle to solve them.

Then we would have multiple connect() for all main "containers" connecting to the main store ?

@gaearon
Copy link
Contributor

gaearon commented Aug 27, 2015

There is no official recommendation on this, it really depends on the app.

Usually I'd go for “one connect() per route handler”, but as your app gets more complicated, you'll want to put connect()s further down the hierarchy. It's a balance you'll need to figure out for yourself. As soon as there's too much prop passing, it's a sign that you should connect().

Then we would have multiple connect() for all main "containers" connecting to the main store ?

Yes.

@farzd
Copy link

farzd commented Nov 6, 2015

Sorry to drag this up but i had a similar question. Because the props are passed from the top level root component, i.e the APP itself, it seems that every inherit component will render.
This doesn't seem to be an issue with other flux implementations as you can have the even listener, listening for updates - somewhere deep in the component hierarchy. ShouldComponentUpdate works ok here but where as in Redux components will need to update to pass the props down.

This seems to be conflicting with React fundamentals where a full app render is taking place all the time?
I'm envisaging performance bottlenecks.

Am i missing something? @gaearon @gnoff

@m4nuC
Copy link
Author

m4nuC commented Nov 6, 2015

Actually you probably dont want to have your root component react to every changes in your store. It should only propagate the "global" state changes like maybe a session change or a language switch.
The rest of your state will be handled by the relevant children.
BTW you can define which part of the store your component will react to using mapStateToProps: https://github.com/rackt/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options

@gaearon
Copy link
Contributor

gaearon commented Nov 6, 2015

Because the props are passed from the top level root component, i.e the APP itself, it seems that every inherit component will render.

I said in the above comment that nobody forces you to connect just once. You can have as many connected components as you like. This addresses any potential performance bottlenecks.

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

No branches or pull requests

4 participants