@samitouri / QOS-React-2 / commits / 28f30b7ef0

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.