props in `getInitialState` as anti-pattern
Cheng Lou committed
Oct 5, 2013 at 02:57 UTC
28f30b7ef0132b0f40b5bab2600cb82c4c24fe0e
2 files changed
+121
docs/cookbook/cb-10-props-in-getInitialSate-as-anti-pattern-tip.md
new
+60
@@ -0,0 +1,60 @@
1
+---
2
+id: props-in-getInitialSate-as-anti-pattern-tip
3
+title: props in getInitialState is an anti-pattern
4
+layout: docs
5
+permalink: props-in-getInitialSate-as-anti-pattern-tip.html
6
+---
7
+
8
+> Note:
9
+>
10
+> This is not really a React-specific tip, as such anti-patterns often occur in code in general; in this case, React simply points them out more clearly.
11
+
12
+Using props, passed down from parent, to generate state in `getInitialState` often leads to duplication of "source of truth", i.e. where the real data is. Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble.
13
+
14
+Bad example:
15
+
16
+```js
17
+/** @jsx React.DOM */
18
+
19
+var MessageBox = React.createClass({
20
+ getInitialState: function() {
21
+ return {nameWithQualifier: "Mr. " + this.props.name};
22
+ },
23
+ render: function() {
24
+ return <div>{this.state.nameWithQualifier}</div>;
25
+ }
26
+});
27
+
28
+React.renderComponent(<MessageBox name="Zuck"/>, mountNode);
29
+```
30
+
31
+Better:
32
+
33
+```js
34
+/** @jsx React.DOM */
35
+
36
+var MessageBox = React.createClass({
37
+ render: function() {
38
+ return <div>{"Mr. " + this.props.name}</div>;
39
+ }
40
+});
41
+
42
+React.renderComponent(<MessageBox name="Zuck"/>, mountNode);
43
+```
44
+
45
+Also works, for larger logic:
46
+
47
+```js
48
+/** @jsx React.DOM */
49
+
50
+var MessageBox = React.createClass({
51
+ render: function() {
52
+ return <div>{this.getNameWithQualifier(this.props.name)}</div>;
53
+ },
54
+ getNameWithQualifier: function(name) {
55
+ return 'Mr. ' + name;
56
+ }
57
+});
58
+
59
+React.renderComponent(<MessageBox name="Zuck"/>, mountNode);
60
+```
docs/cookbook/cb-10-props-in-getInitialSate-as-anti-pattern.md
new
+61
@@ -0,0 +1,61 @@
1
+---
2
+id: props-in-getInitialSate-as-anti-pattern
3
+title: props in getInitialState is an anti-pattern
4
+layout: docs
5
+permalink: props-in-getInitialSate-as-anti-pattern.html
6
+---
7
+
8
+### Problem
9
+You're using `this.props` in a component `getInitialSate`, like so:
10
+
11
+```js
12
+/** @jsx React.DOM */
13
+
14
+var MessageBox = React.createClass({
15
+ getInitialState: function() {
16
+ return {nameWithQualifier: "Mr. " + this.props.name};
17
+ },
18
+ render: function() {
19
+ return <div>{this.state.nameWithQualifier}</div>;
20
+ }
21
+});
22
+
23
+React.renderComponent(<MessageBox name="Zuck"/>, mountNode);
24
+```
25
+
26
+### Solution
27
+Avoid this (see below for explanation). Compute it directly inside `render`:
28
+
29
+```js
30
+/** @jsx React.DOM */
31
+
32
+var MessageBox = React.createClass({
33
+ render: function() {
34
+ return <div>{"Mr. " + this.props.name}</div>;
35
+ }
36
+});
37
+
38
+React.renderComponent(<MessageBox name="Zuck"/>, mountNode);
39
+```
40
+
41
+Or, if the logic's big, isolate it so:
42
+
43
+```js
44
+/** @jsx React.DOM */
45
+
46
+var MessageBox = React.createClass({
47
+ render: function() {
48
+ return <div>{this.getNameWithQualifier(this.props.name)}</div>;
49
+ },
50
+ getNameWithQualifier: function(name) {
51
+ return 'Mr. ' + name;
52
+ }
53
+});
54
+
55
+React.renderComponent(<MessageBox name="Zuck"/>, mountNode);
56
+```
57
+
58
+### Discussion
59
+This is not really a React-specific tip, as such anti-patterns often occur in code in general; in this case, React simply points them out more clearly.
60
+
61
+Using props, passed down from parent, to generate state often leads to duplication of "source of truth", i.e. where the real data is. Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble.