Skip to content

Commit e2dc155

Browse files
author
Chris Bobbe
committed
eslint: Disable react-native/no-inline-styles.
Some styles are most readable when they are inlined. In most cases, this readability is preferred over the performance cost, and the rule interferes with that. For performance, the rule is a bad guide; read the following if you're coming to this from concerns about rerenders. TL;DR: If the utmost effort to reduce rerenders is necessary, we need to rely on more reliable safeguards than a linter rule: the use of PureComponent, especially, or, when that's not ideal (i.e., when finer control using shouldComponentUpdate is needed), memoization techniques that come at a readability cost. First, suppose the component being styled is NOT a PureComponent (PureComponent being the first thing you should try when you want to reduce unnecessary rerenders). The rule gives no false positives, but does give false negatives, for a certain class of unnecessary rerender: those caused by a new object reference being passed for the style prop on an update of the parent, with no change in the prop's information. The pattern of passing an object literal directly as a style prop, without assigning it to a variable, always means a new object reference is created. Since the child is not a PureComponent, this means a rerender each time. The rule does not flag cases outside this pattern, so there are no false positives. However, it's possible (not to mention common) to evade the rule by not strictly inlining the style, while still passing a new object reference indiscriminately on updates of the parent. Where a style depends on values in props or state, it's appropriate to pass a new object reference when props or state change. The most straightforward way to do this is a) to keep the style inline, violating the rule, or b) to declare a const variable in the parent's render method, bypassing the rule, and assign it to a new object literal -- which still always means a new object reference, triggering a rerender. b) is a false negative. Additional false negatives stem from this documented suppression of the error: "If inline styles only contain variable values, the style is considered acceptable because it's sometimes necessary to set styles based on [the parent's] `state` or `props`."; see https://github.com/Intellicode/eslint-plugin-react-native/blob/master/docs/rules/no-inline-styles.md. Note that "variable values" is a superset of variables values that are determined by pure functions of the parent's state or props. Now, suppose the child component IS a PureComponent. There WILL be false positives in this case, which means noise and further unreliability. Passing a new object reference as a prop to a PureComponent does not in itself trigger a rerender because PureComponents do a React-implemented shallow check on props before deciding to update. There will also be false negatives, in a subset of the ones identified for non-PureComponents, above. There will be substantially fewer of them because of the PureComponent optimization, but that optimization goes far beyond what a linter can or should faithfully track.
1 parent 4e05676 commit e2dc155

File tree

2 files changed

+1
-2
lines changed

2 files changed

+1
-2
lines changed

.eslintrc.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ rules:
106106

107107
# React Native. This plugin isn't included in the airbnb config, and
108108
# nothing is enabled by default, so we enable its rules.
109-
react-native/no-inline-styles: error
109+
react-native/no-inline-styles: off # Noisy and a bad guide to rerendering optimizations.
110110
# react-native/no-unused-styles: error # This is buggy on the `this.styles` pattern.
111111
# react-native/no-color-literals: error # TODO eliminate these and enable.
112112

src/webview/MessageList.js

-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,6 @@ class MessageList extends Component<Props> {
321321
source={{ baseUrl, html }}
322322
originWhitelist={['file://']}
323323
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
324-
/* eslint-disable react-native/no-inline-styles */
325324
style={{ backgroundColor: this.context.backgroundColor }}
326325
ref={webview => {
327326
this.webview = webview;

0 commit comments

Comments
 (0)