4 ms·
React.js pure render performance anti-pattern
- andrewingram 11y agoIs it really an anti-pattern when you're just writing code that depends on equality without understanding how equality works? There's probably a lesson to be learned in here, but if I wrote an article every time I wrote bad code, I wouldn't have time to write any bad code ;) Edit: This particular issue is pretty common, and it's good to draw attention to it, but let's just call it what it is - a common bug.
- masklinn 11y ago> Is it really an anti-pattern when you're just writing code that depends on equality without understanding how equality works? The issue here mostly being that PureRenderMixin uses identity because Javascript has little to no support for equality.
- TheCoelacanth 11y agoThe real anti-pattern is languages without value types.
- ashearer 11y ago"Anti-pattern" sounds close enough, as shorthand, when "bug" might cause readers to file the article incorrectly. The author is warning others that a normally-unremarkable JavaScript idiom causes suboptimal performance in this particular case, and it's likely not to present itself as a bug (having no visible symptoms on smaller pages and no impact on functionality otherwise). Putting aside whether suboptimal performance should always be classified as a bug, there are many ways to accidentally break equality comparisons (despite a full understanding of them), and now my eyes are primed to catch one more pitfall. I appreciate when that happens for reason that doesn't involve hard experience.
- andrewingram 11y agoI think calling it a common pitfall might be the most descriptive. I've certainly made the mistakes the article mentions, but I'd never have considered it a pattern. To me a pattern in this context is a repeated practice, workflow or solution.
- danmaz74 11y agoWe just use Immutable.js in our Redux stores. Then, using PureRenderMixin is trivial. You just need to be careful not to use the vanilla reducer composer from Redux.
- masklinn 11y agoDepending on the situation, using PureRenderMixin may be less efficient than an immutable-targeted render mixin as it checks for identity not equality. It's easy to hit cases where Immutable collections are equal but not identical (especially when converting from a base state e.g. list.map(func) will create a new list every invocation, but it may create equal lists across invocations). Depending on how often that happens (and thus subsequent extra reconciliations or even re-renders) versus the cost of checking collections for equality (generally O(n), versus O(1) for identity), you may get extra performances from checking for equality.
- danmaz74 11y agoIf there is some slow component where it is worth spending time to do special optimizations, you can use an equality check - or some component-specific check; but my point is that using Immutable and PureRenderMixin by default will speed up lots of situations without having to do any extra work. Moreover, using Immutable is also much less error-prone.
- andrewingram 11y agoThat's only true if you exclusively use Immutable objects for collections and scalars for individual values, if you pass a date as a prop it's not going to work. > new Date(0) === new Date(0) <- false
- masklinn 11y agoThe same problem exists for Immutable collections: > Immutable.List.of(1) === Immutable.List.of(1) < false = $3 which is why Immutable.is exists.
- fiatjaf 11y agoThis is not an anti-pattern, it's a mistake you made.
- _alexander_ 11y agoWhere is anti-pattern?
- johnhenry 11y agoI think that some of the issues that you're running into might be mitigated by taking advantage of the "key" attribute on repeated elements. There's more here: https://facebook.github.io/react/docs/multiple-components.html#dynamic-children https://facebook.github.io/react/docs/multiple-components.ht...
- cloverich 11y ago(tl;dr) The title is getting a lot of flack but I think there are two good patterns highlighted: 1) Avoid creating functions in React render and 2) Learn about and use defaultProps. 1: Example of arrow functions + Class property initializer: http://babeljs.io/blog/2015/06/07/react-on-es6-plus/ http://babeljs.io/blog/2015/06/07/react-on-es6-plus/ 2: Default Props: https://facebook.github.io/react/docs/reusable-components.html#default-prop-values https://facebook.github.io/react/docs/reusable-components.ht...
- simplify 11y agoIs it wrong for me to think that having a thousand Cell elements on the page is the true anti-pattern? The user can really only see maybe 10-20 at one time. The cost of re-rendering on 15 rows should be trivial enough not to worry about creating a callback function in render. Edit: To elaborate, you can solve this by using pagination (a common solution), or, if you want the user to be able to scroll and not click, occlusion culling. Someone out there must have written an occlusion culling library for React by now, surely.
- simplify 11y agoCould someone explain the downvotes? I'd genuinely like to know what my comment is doing wrong.
- leomelin 11y agoHow do you avoid the e => fn() here in stateless functional component? This is very common case and I can't see other workaround than to use redux mapStateToProps, or without redux maybe mapProps from recompose. Or to use something stupid like writing the item.id into data-attr-id on the li -element and digging out the id -value in the event handler... const List = props => <ul> props.items.map(item => <li onClick={e => props.itemClicked(item.id)}>{item.name}</li> ) </ul>