from the documentation here: http://facebook.github.io/react/docs/pure-render-mixin.html
The footnote is saying that you should use forceUpdate() if the structure of complexe data (deep data structure) is changed.
From the definition of a pure : it renders the same result given the same props and state.
I'm thinking more and more that this is a contradiction because if the data structure changes, it means that you are giving new props/state. Thus the component is not "pure" anymore.
In my opinion, if you change the props or state that is passed to the component you can either:
use forceUpdate().
remove PureRenderMixin from the mixins.
Thus, under the hood... you are transforming a component that is pure to a "non-pure" component. So removing PureRenderMixin should be the only option available.
Am I right ? Or a Pure component means that the component is "cached" and reused when giving the same props ?
Sorry but I'm a bit confused here.
PureRenderMixin is used to give React a way of knowing that it shouldn't call your render method unnecessarily. For example, if your render method is complex enough, it can give you a performance boost if your component isn't being re-rendered with the same props/state.
But, like it's said in the documentation, PureRenderMixin does not compare deeply nested data structures, so it might not call your render function, when it should have, because some nested structure actually changed.
In these cases, it's better to not use PureRenderMixin and use shouldComponentUpdate and perform you own comparison logic.
Also, from the docs, you should avoid using forceUpdate.
The absence of side effect is an important aspect of the mixin because it enables the logic of not rendering the component twice given the same state.
That shouldn't be a satisfying answer because, as you pointed out, nested changes won't be caught by the shallow checking... Unless your data structure are immutable!
I strongly recommend watching Lee Byron's talk on immutable data structures which explains how immutable data improves the performance of your application by avoiding a whole class of problems.
Essentially, a smart library like immutable.js will share common state between two snapshots of an immutable object.
Therefore shallow equality becomes a proof of the underlying data not being changed.
Related
This has come about because during prototyping, I'm finding that incoming new prop(s) might be an array of complex objects, so prevProps.myProp===this.props.myProp is always false. JSON.stringifying them both before comparison works, but feels unreliable.
I'm trying to write a reusable function for Class Components that compares prev/new props in react's componentDidUpdate. For example:
componentDidUpdate(prevProps) {
// First, get difference here, possibly using a lib like npm 'deep-object-diff'.
// ...or just JSON.stringify both and do string comparison
const changes = getTheDifference(prevProps, this.props)
// Don't do anything if there's no changes.
if (!changes) return
// Then I want to do something like:
this.setState( Object.assign(this.state, changes) )
}
...that would mean any time the incoming props change, those get immediately reflected in state. I'm having some issues finding a suitable diff lib, but I still feel like I shouldn't be having to do this and am missing something - is there a generally accepted "normal" way to do this, or is me having this problem just a sign of:
The component is trying to do too much/state too complex?
I should be mapping props to state with something like Redux? (trying to avoid this until absolutely necessary)
I'm overthinking it, sometimes the logic in a component's componentDidUpdate is just complex and unique?
that would mean any time the incoming props change, those get immediately reflected in state
Yes, that's wrong. When I first started out I was doing the same thing.
state is something "owned" by that component (noteworthy: not all components need state at all!).
props are something that are "owned" by a higher component.
Best example:
ComponentA passed an id to ComponentB as a prop. ComponentB uses that id to make an API request (for example).
The status/results of that API request form part of ComponentB's state (it's "owned" by your component). The id passed in as a prop is NOT part of ComponentB's state (it's owned by ComponentA, or maybe somewhere higher in the tree that passed it as a prop to ComponentA).
When the id prop changes, ComponentB will need to make another API request.
EDIT:
The complexity of lifecycle methods is why React has highly encouraged functional components.
You should think of components as functions. It's a lot easier to write the logic if you just think of it as input -> output.
componentDidUpdate has been moved to useEffect with a dependency list so you can say - run this function, but only when this prop changes - which is a nice way to break down massive componentDidUpdate methods into tiny readbale/testable chunks.
I've heard a lot of people say hooks ruined react, but I highly disagree with them. React saw the problems people were running into in the community by misusing class/instance based components and instead of lecturing about how to use them correctly, they nudged people to writing better components by introucing a simpler API - functions, while they still can and will be abused - are generally simpler to deal with than classes and align nicely with composition over inheritance and declarative over imperative.
~Disclaimer: this is an architecture question and contains traces of pseudocode.~
Assuming the following components:
<MapScreen>
<Map filters={filtersObject}/>
<MapFilters
filtersChanged={callback} //where callback returns a filters object
/>
</MapScreen>
And a filters object looking ~like
filters = [{
filterName: String
filterColor: String
}, ...]
There's a lot of ways to implement this but im more interested in the thinking behind which implementation to choose
The questions
A) Given that <Map Screen/> doesnt need to be aware of the filters object in itself, is it desireable to pass the filters object from the callback somehow (e.g redux) directly to the <Map/> object?
B) Yes <Map Screen/> could hold the filter state but it doesnt do anything with it other than grabbing it and propagating it back down so it just feels like i'd be designing my seperation of concerns based on convenience..
C) Many people are in favor of the B) way. If so, then there's the question of, should then <Map Filters/> only emit the filtersObject and receive it back in as a property instead of also storing it to it's own state thus avoiding having two states for the same thing?
I know the question here is very much up to personal taste but i'd love to hear your thoughts on this.
Many thanks.
A. Yes. If data need to be shared between components, redux or other data flow solutions is perfectly fine here.
B. If the data shared between Map and MapFilter is never used anywhere else or just inside MapScreen and its children, then MapScreen can hold the data in its state and pass as props to its children. This approach is commonly used since React components are designed to work for data flow between parent-child. However, you need to consider following trade-offs of this approach:
Since the data is shared by MapScreen and its children, whenever data changes it will trigger MapScreen along with all its children to re-render. Depending on the size of the data, how frequently data is updated and number of children of MapScreen, approach B might be inferior in term of performance to approach A.
If you are dealing with animation in any children of MapScreen, e.g. Map and want to provide smooth and unnoticeable animation whenever data is updated, then it's very difficult to control since it is always forced to re-render along with the parental component MapScreen. Of course you can use shouldComponentUpdate to control re-rendering behaviour, but you have to put it in MapScreen instead of putting directly in the children component. Then if you use approach A, MapScreen will be a dumb component which is blind to whatever happens between its children.
C. Even without using redux, keeping only one single source of truth is important. MapScreen should act as that source of truth by keeping data in its own state, passing state data as props to its children and listening to callbacks from its children to update state.
If you are absolutely fine with (B1) and (B2), then I highly recommend you to go for approach B, since pure React solution is usually clearer and faster than using add-in libraries. But if your data is still growing and you want to add more behaviours in the future, then go for A.
I'm having a huge form built with react and material-ui. The form uses two way binding and update state for input changes. changing any input filed cause all components to update (obvious by react developer tools TraceReactUpdate enabled). When it comes to TextField it makes my page rendering very slow. using this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this) doesn't help.
It can be extremely difficult to find issues like the above, because it totally depends on the actual code you have written. I am sure that the react rendering concept works (as it has for myself and so many others), but without seeing more code it is impossible to pinpoint the actual problem.
Still, I have a feeling that the real cause is "simple", meaning that it is very likely due to a prop being passed that has indeed changed. Maybe not in value, but in instance. IIRC, the PurerenderMixin is not comparing values (unless the data are value types), it is comparing instances. So even if the data is the same, if the instance has changed then it will re-render.
Some key-points to consider:
Are you passing just the props that you need to each component, or are you passing all props to them all?
Are the data-structures immutable?
Are you sure that you are not passing data that changes on the iterations, like passing the javascript [] as a prop will mean that the data has changed (see https://medium.com/#esamatti/react-js-pure-render-performance-anti-pattern-fb88c101332f#.hx97qk4tx for sample on how this can screw up your day).
If you explicitly create a shouldComponentUpdate() method for the components then you can control this yourself. The PureRenderMixin does a shallow check to see if the props have changed, but, if you are passing them all then no matter if they have been used or not in the render method then just one of them changing will mean that the component is considered to need to render (as in, not mount, but render in memory and reconcile possible changes with the dom). Using shouldComponentUpdate can help stop rendering based on your own checks.
Using immutable props can also be helpful. The React PureRenderMixin only does a shallow comparison, as mentioned. So, if you are passing data-structures in the props that have depth (like sub-properties), then these are not checked. Meaning that you could end up with the opposite problem you have now, that is components that should have updated but aren't. If you are using i.e. redux and have done "the right thing" and are using i.e. Immutable.js, then using the PureRenderMixin is good enough.
Reading the specific docs for this may or may not help. There's some good description of this in the React manuals: https://facebook.github.io/react/docs/advanced-performance.html#shouldcomponentupdate-in-action
And - I forgot to say, if you are using redux then you could consider these somewhat elegant and simple ways of handling your forms:
http://redux-form.com/
https://davidkpiano.github.io/react-redux-form/
Hope that this helps. Good luck.
So I started learning React a week ago and I inevitably got to the problem of state and how components are supposed to communicate with the rest of the app. I searched around and Redux seems to be the flavor of the month. I read through all the documentation and I think it's actually a pretty revolutionary idea. Here are my thoughts on it:
State is generally agreed to be pretty evil and a large source of bugs in programming. Instead of scattering it all throughout your app Redux says why not just have it all concentrated in a global state tree that you have to emit actions to change? Sounds interesting. All programs need state so let's stick it in one impure space and only modify it from within there so bugs are easy to track down. Then we can also declaratively bind individual state pieces to React components and have them auto-redraw and everything is beautiful.
However, I have two questions about this whole design. For one, why does the state tree need to be immutable? Say I don't care about time travel debugging, hot reload, and have already implemented undo/redo in my app. It just seems so cumbersome to have to do this:
case COMPLETE_TODO:
return [
...state.slice(0, action.index),
Object.assign({}, state[action.index], {
completed: true
}),
...state.slice(action.index + 1)
];
Instead of this:
case COMPLETE_TODO:
state[action.index].completed = true;
Not to mention I am making an online whiteboard just to learn and every state change might be as simple as adding a brush stroke to the command list. After a while (hundreds of brush strokes) duplicating this entire array might start becoming extremely expensive and time-consuming.
I'm ok with a global state tree that is independent from the UI that is mutated via actions, but does it really need to be immutable? What's wrong with a simple implementation like this (very rough draft. wrote in 1 minute)?
var store = { items: [] };
export function getState() {
return store;
}
export function addTodo(text) {
store.items.push({ "text": text, "completed", false});
}
export function completeTodo(index) {
store.items[index].completed = true;
}
It's still a global state tree mutated via actions emitted but extremely simple and efficient.
Isn't Redux just glorified global state?
Of course it is. But the same holds for every database you have ever used. It is better to treat Redux as an in-memory database - which your components can reactively depend upon.
Immutability enables checking if any sub-tree has been altered very efficient because it simplifies down to an identity check.
Yes, your implementation is efficient, but the entire virtual dom will have to be re-rendered each time the tree is manipulated somehow.
If you are using React, it will eventually do a diff against the actual dom and perform minimal batch-optimized manipulations, but the full top-down re-rendering is still inefficient.
For an immutable tree, stateless components just have to check if the subtree(s) it depends on, differ in identities compared to previous value(s), and if so - the rendering can be avoided entirely.
Yes it is!!!
Since there is no governance of who is allowed to write a specific property/variable/entry to the store and practically you can dispatch any action from anywhere, the code tends to be harder to maintain and even spaghetti when your code base grows and/or managed by more than one person.
I had the same questions and issues with Redux when I started use it so I have created a library that fix these issue:
It is called Yassi:
Yassi solves the problems you mentioned by define a globally readable and privately writable store. It means that anyone can read a property from the store (such as in Redux but simpler).
However only the owner of the property, meaning the object that declare the property can write/update that property in the store
In addition, Yassi has other perks in it such as zero boilerplate to declare entry in the store by using annotations (use #yassit('someName'))
Update the value of that entry does not require actions/reducers or other such cumbersome code snippets, instead just update the variable like in regular object.
I am a bit confused by the statements: "Renders the whole application" and "Passing state to child components".
Example 1:
I have a todos app with a AppComponent and TodosListComponent. The AppComponent grabs the array of todos from the store and passes it as a property to the TodosListComponent.
Example 2:
I have a huge application with lots state. I have like 50 components building up my app. Do I want to pass all the state from the stores from AppComponent down through all the 50 components?
So I am wondering, what is the convention? It makes more sense to me to let individual components listen directly to the stores they care about. The advantage is that only individual components rerender, but why then the concept of "the whole application rerender on state change"?
What are the pros and cons of each? What is the common convention?
There are a few ways you can handle this. I think they're all valid and have their own trade-offs.
Get all the state and pass pieces of it to children
This is the technique you specifically asked about. Using this method, you'll have some function or method available to your top-level component that turns all the data from the stores into a "big bag of state" and then you'll selectively pass pieces of this data to child components. If those components have their own children, they'll pass it along as necessary.
The upside to this method is that it makes things generally easy to debug. If you have to change the way a piece of state is retrieved from a store, you only have to change it in the top-level component—as long as it gets passed down with the same name, the other components will "just work." If some piece of data is wrong, you should only need to look in one place to figure out why.
The downside to this technique what I call "props explosion"—you can end up passing a lot of properties around. I use this method in a medium-sized flux application, and a snippet of the top-level application component looks like this:
<section id="col-left">
<Filters loading={this.state.loading}
events={this.state.events}
playbackRate={this.state.videoPlayback.playbackRate}
autoPlayAudio={this.state.audioPlayback.autoPlay}
role={this.state.role} />
</section>
<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
<SessionVideo videoUuid={this.state.session.recording_uuid}
lowQualityVideo={this.state.session.low_quality_video_exists}
playbackRate={this.state.videoPlayback.playbackRate} />
<section id="transcript">
<Transcript loading={this.state.loading}
events={this.state.events}
currentEvents={this.state.currentEvents}
selection={this.state.selection}
users={this.state.session.enrolled_users}
confirmedHcs={this.state.ui.confirmedHcs}
currentTime={this.state.videoPlayback.position}
playing={this.state.videoPlayback.playing} />
</section>
</section>
In particular, there can be a lot of components between the top-level one and some eventual child that do nothing with the data except pass it along, more closely coupling those components to their position in the hierarchy.
Overall, I like the debuggability this technique provides, though as the application grew larger and more complex I found it was not idea to do this with only a single top-level component.
Get all the state and pass it as one object
One of the developers at Facebook mentioned this technique. Here, you'll get a big bag of state, just as above, but you'll pass the whole thing (or entire sub-sections of it) rather than individual properties. By utilizing React.PropTypes.shape in child components, you can ensure that the right properties are getting passed.
The upside is you pass way fewer properties around; the above example might look more like this:
<section id="col-left">
<Filters state={this.state} />
</section>
<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
<SessionVideo session={this.state.session}
playback={this.state.videoPlayback} />
<section id="transcript">
<Transcript state={this.state} />
</section>
</section>
The downside is that it becomes a little more difficult to deal with changes in the shape of the state; rather than just changing the top-level component, you'll have to track down everywhere that piece of data is used and change the way that component access the property. Also, shouldComponentUpdate can potentially become a little trickier to implement.
Allow components to get their own state
On the other end of the spectrum, you can grant application-specific (that is, non-reusable) child components to access the stores and build up their own state based on the store change events. Components that build their own state like this are sometimes called "controller-views" or, more commonly these days, "container components."
The upside, of course, is that you don't have to deal with passing properties around at all (other than change handlers and properties for more reusable components).
The downside, though, is that your components are more highly coupled to the stores—changing the stores or the data they provide (or the interface via which they provide that data) may force you to revisit the code for a larger number of components.
Also, as mentioned in the comments, this can potentially make server rendering a bit more difficult. If you only use properties (especially at only the top level), you can transport them more easily to the client and re-initialize React with the same properties. By allowing the stores to determine their own data, you need to somehow inject that data into the stores to allow the components to get that data.
A common approach, and one that I typically use now, is to make every component in your application only rely on props for global application state, and then decide if it makes more sense to (1) connect them directly to flux by wrapping them in a container, or (2) allow the props to be passed from some parent container.
There are abstractions that you might be able to use to make some of these techniques more viable. For example, a Facebook dev had this to say in a comment on Hacker News:
Now all your data is in stores, but how do you get it into the specific component that needs it? We started with large top level components which pull all the data needed for their children, and pass it down through props. This leads to a lot of cruft and irrelevant code in the intermediate components. What we settled on, for the most part, is components declaring and fetching the data they need themselves, except for some small, more generic components. Since most of our data is fetched asynchronously and cached, we've created mixins that make it easy to declare which data your component needs, and hook the fetching and listening for updates into the lifecycle methods (componentWillMount, etc).
Jason Bonta from Facebook explained the concept of "Containers" in his React.js Conf 2015 talk.
To summarize: containers are simply components that wrap other components, and take care of any data-related concerns such as talking to stores, while the underlying component is focused solely on the view (markup/styles/etc.) and doesn't care where the data comes from.
This makes the component
highly re-usable because it can be wrapped with a different container when data needs to come from a different place,
not contain irrelevant state, therefore easier to implement and optimize shouldComponentUpdate, and
using composition rather than mixins for this aligns with what is likely the future of React with ES6, which does not have idiomatic mixins.
UPDATE March 2019: Look into React Hooks. With hooks, you can accomplish the same goal as described above, but abstract data-related concerns, such as talking to stores, in re-usable chunks of code that can be applied to multiple components. The ReactConf talk React Today and Tomorrow and 90% Cleaner React With Hooks by Dan Abramov does a great job of explaining hooks, and how they are different from both mixins and past composition approaches.