-
Notifications
You must be signed in to change notification settings - Fork 0
/
1.8.tsx
206 lines (167 loc) · 7.05 KB
/
1.8.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/***************** Keeping Components Pure *********************/
/**
* - Some JavaScript functions are pure. Pure functions only perform a calculation and nothing more.
* By strictly only writing your components as pure functions, you can avoid an entire
* class of baffling bugs and unpredictable behavior as your codebase grows.
*/
/******* Purity: Components as formulas ********/
/**
* In computer science (and especially the world of functional programming), a pure function
* is a function with the following characteristics:
*
* - It minds its own business. It does not change any objects or variables that existed before it was called.
* - Same inputs, same output. Given the same inputs, a pure function should always return the same result.
*
* - You might already be familiar with one example of pure functions: formulas in math:
Consider this math formula: y = 2x.
If x = 2 then y = 4. Always.
If x = 3 then y = 6. Always.
If x = 3, y won’t sometimes be 9 or –1 or 2.5 depending on the time of day or the state of the stock market.
If y = 2x and x = 3, y will always be 6.
If we made this into a JavaScript function, it would look like this:
function double(number) {
return 2 * number;
}
In the above example, double is a pure function. If you pass it 3, it will return 6. Always.
*
*
*/
/**
*
*
*
function Recipe({ drinkers }) {
return (
<ol>
<li>Boil {drinkers} cups of water.</li>
<li>Add {drinkers} spoons of tea and {0.5 * drinkers} spoons of spice.</li>
<li>Add {0.5 * drinkers} cups of milk to boil and sugar to taste.</li>
</ol>
);
}
export default function App() {
return (
<section>
<h1>Spiced Chai Recipe</h1>
<h2>For two</h2>
<Recipe drinkers={2} />
<h2>For a gathering</h2>
<Recipe drinkers={4} />
</section>
);
}
When you pass drinkers={2} to Recipe, it will return JSX containing 2 cups of water. Always.
If you pass drinkers={4}, it will return JSX containing 4 cups of water. Always.
Just like a math formula.
*
*/
/**
* -You could think of your components as recipes: if you follow them and don’t introduce
* new ingredients during the cooking process, you will get the same dish every time. That
* “dish” is the JSX that the component serves to React to render.
*/
/******* Side Effects: (un)intended consequences ********/
/**
* - React’s rendering process must always be pure. Components should only return their JSX, and
* not change any objects or variables that existed before rendering—that would make them impure!
* Here is a component that breaks this rule:
let guest = 0;
function Cup() {
// Bad: changing a preexisting variable!
guest = guest + 1;
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaSet() {
return (
<>
<Cup />
<Cup />
<Cup />
</>
);
}
*
* - This component is reading and writing a guest variable declared outside of it. This means
* that calling this component multiple times will produce different JSX! And what’s more,
* if other components read guest, they will produce different JSX, too, depending on when
* they were rendered! That’s not predictable.
*
* - You can fix this component by passing guest as a prop instead:
function Cup({ guest }) {
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaSet() {
return (
<>
<Cup guest={1} />
<Cup guest={2} />
<Cup guest={3} />
</>
);
}
*
*/
/**
* - In general, you should not expect your components to be rendered in any particular order.
* It doesn’t matter if you call y = 2x before or after y = 5x: both formulas will resolve
* independently of each other.
*
* - In the same way, each component should only “think for itself”, and not attempt to
* coordinate with or depend upon others during rendering. Rendering is like a school exam:
* each component should calculate JSX on their own!
*/
/******* Detecting impure calculations with StrictMode ********/
/**
* - In React there are three kinds of inputs that you can read while rendering: props, state,
* and context. You should always treat these inputs as read-only.
*
* - When you want to change something in response to user input, you should set state instead of
* writing to a variable. You should never change preexisting variables or objects while your
* component is rendering.
*
* - React offers a “Strict Mode” in which it calls each component’s function twice during
* development. By calling the component functions twice, Strict Mode helps find components
* that break these rules.
*
*/
/******* Local mutation: Your component’s little secret ********/
/**
* - In the above example, the problem was that the component changed a preexisting variable while
* rendering. This is often called a “mutation” to make it sound a bit scarier.
*
* - Pure functions don’t mutate variables outside of the function’s scope or objects that were
* created before the call—that makes them impure!
*
* - However, it’s completely fine to change variables and objects that you’ve just created while rendering.
*
* - In this example, you create an [] array, assign it to a cups variable,
* and then push a dozen cups into it:
function Cup({ guest }) {
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaGathering() {
let cups = [];
for (let i = 1; i <= 12; i++) {
cups.push(<Cup key={i} guest={i} />);
}
return cups;
}
- If the cups variable or the [] array were created outside the TeaGathering function, this would be
a huge problem! You would be changing a preexisting object by pushing items into that array.
- However, it’s fine because you’ve created them during the same render, inside TeaGathering.
No code outside of TeaGathering will ever know that this happened. This is called
“local mutation”—it’s like your component’s little secret.
*
*
*/
/******* Where you can cause side effects ********/
/**
* - These changes—updating the screen, starting an animation, changing the data—are called
* side effects. They’re things that happen “on the side”, not during rendering.
*
* - In React, side effects usually belong inside event handlers. Even though event handlers are defined
* inside your component, they don’t run during rendering! So event handlers don’t need to be pure.
*
* - If even handlers is not an option, use useEffect. This tells React to execute it later, after
* rendering, when side effects are allowed. However, this approach should be your last resort.
*/