Compare commits
582 Commits
v16.5.0
...
v15.4.0-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c577b82875 | ||
|
|
2d049e8df6 | ||
|
|
c8c879f1c5 | ||
|
|
a107f6d12e | ||
|
|
4717d2480c | ||
|
|
91dc94cec6 | ||
|
|
c7020c017d | ||
|
|
9b025df36b | ||
|
|
b0b1303207 | ||
|
|
4f20847f8b | ||
|
|
3e95d99fe2 | ||
|
|
1dce444f70 | ||
|
|
4dfe234950 | ||
|
|
8ecaaddd23 | ||
|
|
a793486541 | ||
|
|
6b85431df6 | ||
|
|
32edcfc9cd | ||
|
|
a28dc34918 | ||
|
|
3135f888f0 | ||
|
|
84fc62f30f | ||
|
|
c4c7e0a966 | ||
|
|
918037bd30 | ||
|
|
71f0c6fef9 | ||
|
|
a6bdb0022f | ||
|
|
1d93d28494 | ||
|
|
c3d43193c9 | ||
|
|
da9a658e35 | ||
|
|
3bc9d9caa7 | ||
|
|
d5059c91f5 | ||
|
|
ec4c0f1dd6 | ||
|
|
4d99f2bdd4 | ||
|
|
ce1f57e940 | ||
|
|
2fbe0cd333 | ||
|
|
747d65133a | ||
|
|
195b03e196 | ||
|
|
c023d53f02 | ||
|
|
c1f0b4e9da | ||
|
|
26d060797c | ||
|
|
118b93c591 | ||
|
|
654829da66 | ||
|
|
88e29060cd | ||
|
|
a7b81a60c0 | ||
|
|
db985af3c3 | ||
|
|
2c16a6bb9d | ||
|
|
b4949fd8c6 | ||
|
|
206bc2a330 | ||
|
|
2c00d750c2 | ||
|
|
ae79e023d5 | ||
|
|
bef7ae4800 | ||
|
|
b7d7f47a5e | ||
|
|
85de53c450 | ||
|
|
96d39380fa | ||
|
|
d5a769ec89 | ||
|
|
869d26c3b4 | ||
|
|
c3f2c6b19d | ||
|
|
465d35a78a | ||
|
|
bf3f9cffc2 | ||
|
|
4b7f7b371b | ||
|
|
0dd4ff1bc8 | ||
|
|
577818e419 | ||
|
|
2589ed586d | ||
|
|
b9ce809aaf | ||
|
|
dd01e016a6 | ||
|
|
329b107606 | ||
|
|
fb7b8f201f | ||
|
|
74da40520c | ||
|
|
f5f0256d82 | ||
|
|
25bdc55fb8 | ||
|
|
f5f1c749b6 | ||
|
|
951b243d17 | ||
|
|
a9b2d841f7 | ||
|
|
58d6f4fac6 | ||
|
|
03846d6916 | ||
|
|
774a94b6c2 | ||
|
|
283dbc30ee | ||
|
|
f4374bd168 | ||
|
|
87958ea037 | ||
|
|
52235eadfd | ||
|
|
cb963b09ab | ||
|
|
1fb75eaa9e | ||
|
|
a71a787038 | ||
|
|
cbc450860e | ||
|
|
ecdc185deb | ||
|
|
cc2e5cc3d7 | ||
|
|
5c2a88a9a1 | ||
|
|
5bc9daa125 | ||
|
|
21a4e7a826 | ||
|
|
556bd43a26 | ||
|
|
8426fafe90 | ||
|
|
7ae3bbee25 | ||
|
|
bada298857 | ||
|
|
5a540f778a | ||
|
|
bed4c0595c | ||
|
|
0c89348be4 | ||
|
|
53d16f86fd | ||
|
|
ecd66274a7 | ||
|
|
586f487ea9 | ||
|
|
03e7900edb | ||
|
|
345329e079 | ||
|
|
f5798f729d | ||
|
|
dcd34ab6c1 | ||
|
|
8a78b2497a | ||
|
|
58d66ad47f | ||
|
|
f6448ff595 | ||
|
|
4421c71120 | ||
|
|
9a6ef44a06 | ||
|
|
ae5ebe3d92 | ||
|
|
0c59b3c71f | ||
|
|
6e58219117 | ||
|
|
6259f15e33 | ||
|
|
e48635bd59 | ||
|
|
cf592f29bc | ||
|
|
00e9080314 | ||
|
|
17336bc8ee | ||
|
|
1df0e8a012 | ||
|
|
66a279df53 | ||
|
|
5eb67ed4e2 | ||
|
|
fcd42c1e28 | ||
|
|
c99abadafb | ||
|
|
8753a838cf | ||
|
|
749e809478 | ||
|
|
fb37b44e79 | ||
|
|
8f8a26c091 | ||
|
|
c2e9167e45 | ||
|
|
13ef94ad46 | ||
|
|
c2388bf09b | ||
|
|
b52ea6bd8f | ||
|
|
bdf263625d | ||
|
|
8c7bbbfc21 | ||
|
|
15631e02a2 | ||
|
|
1907f72934 | ||
|
|
ba62748217 | ||
|
|
224ace32be | ||
|
|
3ef748abb3 | ||
|
|
3f8b8d754c | ||
|
|
7a18e4e00b | ||
|
|
60ed71459c | ||
|
|
7b39bbaa91 | ||
|
|
2927c4ce76 | ||
|
|
3e47b3002b | ||
|
|
1bac6d567f | ||
|
|
92cfbf16c2 | ||
|
|
b445b26164 | ||
|
|
832c503c92 | ||
|
|
076d7fd63a | ||
|
|
3ed71070a3 | ||
|
|
08dbefedc7 | ||
|
|
4be377650e | ||
|
|
8898803b4a | ||
|
|
21f71d72f0 | ||
|
|
d79061e0c6 | ||
|
|
d951c560e4 | ||
|
|
6cf782b75c | ||
|
|
dca0f7315c | ||
|
|
0983d2dbcf | ||
|
|
d90cbec236 | ||
|
|
6e20d410bb | ||
|
|
b4f6460bff | ||
|
|
199056cf1b | ||
|
|
681c68c62a | ||
|
|
cc41ec258f | ||
|
|
3c0906ca24 | ||
|
|
60a3655469 | ||
|
|
15df676d2e | ||
|
|
e5276bbbe7 | ||
|
|
12ab5baff4 | ||
|
|
f120c1b78e | ||
|
|
421bb8c53a | ||
|
|
9fea8ec6c8 | ||
|
|
536f826b56 | ||
|
|
307b4ebcc9 | ||
|
|
e1a9eb13b1 | ||
|
|
51fe7e466e | ||
|
|
8403a28adc | ||
|
|
c4f8466d5d | ||
|
|
cc5889c543 | ||
|
|
9e88467485 | ||
|
|
bfb3852942 | ||
|
|
df4356133d | ||
|
|
814be45aa8 | ||
|
|
bab9227e9d | ||
|
|
2f1ce9169d | ||
|
|
b19f202542 | ||
|
|
71f12283d9 | ||
|
|
4c5882258c | ||
|
|
ce24114a01 | ||
|
|
8e79c9fd30 | ||
|
|
5372e66c0c | ||
|
|
94dbf619d3 | ||
|
|
9d7ceac1f3 | ||
|
|
6a992382a4 | ||
|
|
c93d0c4f30 | ||
|
|
f2010e5532 | ||
|
|
5dce7c21e3 | ||
|
|
382f1519b2 | ||
|
|
38914dfe6a | ||
|
|
f65d629541 | ||
|
|
7608eda1ff | ||
|
|
21d9b85d66 | ||
|
|
44fa2c83d1 | ||
|
|
bad1080586 | ||
|
|
992e11b852 | ||
|
|
043c249458 | ||
|
|
d551e19b18 | ||
|
|
58720d608e | ||
|
|
3c7f275f4f | ||
|
|
77d6143485 | ||
|
|
d0fc12db61 | ||
|
|
ae17ce5b03 | ||
|
|
8794c51389 | ||
|
|
8a1c16bf09 | ||
|
|
1f65b2901b | ||
|
|
9be069fb98 | ||
|
|
b194f66fbc | ||
|
|
1d4e8c958d | ||
|
|
b071f10dd7 | ||
|
|
44f63165cb | ||
|
|
cc01d1be33 | ||
|
|
66cee497e7 | ||
|
|
7251f6a6e9 | ||
|
|
f7837682b4 | ||
|
|
41f21520d1 | ||
|
|
e5efe5f568 | ||
|
|
396ab3eba1 | ||
|
|
01ad9af590 | ||
|
|
5d2f6c07c3 | ||
|
|
6cab7064a0 | ||
|
|
6f80ed8615 | ||
|
|
88d49edda5 | ||
|
|
5f705664fa | ||
|
|
6fba1f1fad | ||
|
|
127af0ffc7 | ||
|
|
86f72d0830 | ||
|
|
9423829db2 | ||
|
|
f8a698e9af | ||
|
|
807244badd | ||
|
|
2106bf5085 | ||
|
|
2debcef8f6 | ||
|
|
7cdcb4f696 | ||
|
|
8f8e215df1 | ||
|
|
0c56ee7a89 | ||
|
|
dfebed11c2 | ||
|
|
0394bae0e3 | ||
|
|
1e4828d9fc | ||
|
|
108f25350d | ||
|
|
f40b5b5c47 | ||
|
|
b38bbde2fe | ||
|
|
939071d737 | ||
|
|
42d7d0adad | ||
|
|
14e6a69a46 | ||
|
|
b1e1ccf632 | ||
|
|
7b78757c6f | ||
|
|
7d3cf9565e | ||
|
|
86cc1d4e67 | ||
|
|
80d09bfbb3 | ||
|
|
615ae2f497 | ||
|
|
1c3b4af564 | ||
|
|
40cc8fa45f | ||
|
|
ea61ddb0d0 | ||
|
|
9f975293e1 | ||
|
|
d40393fde7 | ||
|
|
8517e99816 | ||
|
|
cf07f0cab1 | ||
|
|
ddb58dd9f3 | ||
|
|
7d9ded56a2 | ||
|
|
e75e8dcbeb | ||
|
|
4a0a534357 | ||
|
|
d441128bf6 | ||
|
|
891e087926 | ||
|
|
9d385ef326 | ||
|
|
3b80d4dcd7 | ||
|
|
343033bf06 | ||
|
|
b688bb301c | ||
|
|
9138b45e82 | ||
|
|
1b7f871819 | ||
|
|
52e45997db | ||
|
|
45547d1c3b | ||
|
|
0f520b8cc0 | ||
|
|
5478d76271 | ||
|
|
57a1ebb809 | ||
|
|
dfb5cc306f | ||
|
|
ea880f2e2c | ||
|
|
68faf9d1b9 | ||
|
|
5597ca70be | ||
|
|
4b9d48a150 | ||
|
|
6b19617333 | ||
|
|
86d696d933 | ||
|
|
e685ca9126 | ||
|
|
abaa9a8760 | ||
|
|
ebabd2f8cd | ||
|
|
c51e8a1523 | ||
|
|
9fb898943a | ||
|
|
ccd781d97e | ||
|
|
9db68fcf5d | ||
|
|
219e838070 | ||
|
|
720ce5aa70 | ||
|
|
a0a8f2a451 | ||
|
|
67cc922747 | ||
|
|
75e6399261 | ||
|
|
25528eacbc | ||
|
|
f6b619aab1 | ||
|
|
7547d0d8e5 | ||
|
|
d7a6c95464 | ||
|
|
9687b35d83 | ||
|
|
173d065a9e | ||
|
|
67cbe6d471 | ||
|
|
c625bc88aa | ||
|
|
f1f599d775 | ||
|
|
c4b719d4dc | ||
|
|
e23690a0dc | ||
|
|
20d2398ab6 | ||
|
|
32cadeacdb | ||
|
|
a3c0d68af9 | ||
|
|
24cf5c7a5e | ||
|
|
8ea1ee14d5 | ||
|
|
ec029f66cc | ||
|
|
ba6ca7ff71 | ||
|
|
eb9f4efde7 | ||
|
|
8ee93720ce | ||
|
|
cea00b4b21 | ||
|
|
f3c9508e95 | ||
|
|
23de673537 | ||
|
|
26870ad27b | ||
|
|
54ee110436 | ||
|
|
a011a23090 | ||
|
|
0d4c994471 | ||
|
|
bc1d59ee19 | ||
|
|
3a6584b2ee | ||
|
|
c650249339 | ||
|
|
516aa96419 | ||
|
|
1808ecb348 | ||
|
|
74c29b391a | ||
|
|
33f54bfaa1 | ||
|
|
5131a43f96 | ||
|
|
62135da3ba | ||
|
|
7fbbb535ff | ||
|
|
bda788e932 | ||
|
|
ec44f2af6d | ||
|
|
6059444c84 | ||
|
|
814bf1ca0c | ||
|
|
aaa496213e | ||
|
|
c66f40f749 | ||
|
|
e921abf260 | ||
|
|
d893ab6428 | ||
|
|
dbb67824a4 | ||
|
|
592abf8ee7 | ||
|
|
2a411dd248 | ||
|
|
909d647801 | ||
|
|
243be87c6d | ||
|
|
eab4ffa721 | ||
|
|
1e0f0a35cf | ||
|
|
d4aebaa671 | ||
|
|
cd5189a63c | ||
|
|
cf50a83b8d | ||
|
|
89746fa70f | ||
|
|
e1c2c42c24 | ||
|
|
05c133a9c3 | ||
|
|
92bda144d9 | ||
|
|
6eeb2898f7 | ||
|
|
e974383cba | ||
|
|
7912baea69 | ||
|
|
07389fd9fc | ||
|
|
7a4aef0d0d | ||
|
|
85fd90d4c2 | ||
|
|
6080ab547d | ||
|
|
6562466c9e | ||
|
|
904c6e767b | ||
|
|
58634bda69 | ||
|
|
cb10a45ded | ||
|
|
90007f7087 | ||
|
|
39ddfdd9a2 | ||
|
|
ab4ea744f9 | ||
|
|
60cc2fe911 | ||
|
|
74ea71b324 | ||
|
|
3d748e93f1 | ||
|
|
a5d7fc84ee | ||
|
|
e8a8d005f0 | ||
|
|
2f4c61d1be | ||
|
|
677dd27912 | ||
|
|
689f5cc187 | ||
|
|
8f8d9a9dde | ||
|
|
634b107491 | ||
|
|
31ba751d2e | ||
|
|
c8b2a3dc13 | ||
|
|
58313419e2 | ||
|
|
8e598ea5c6 | ||
|
|
58f0298c62 | ||
|
|
f98e6c1955 | ||
|
|
a2f7b34f38 | ||
|
|
fad173a0f9 | ||
|
|
c1a9d1c0e0 | ||
|
|
3cf363384e | ||
|
|
bff0662ba3 | ||
|
|
8b6749dedd | ||
|
|
00095e3cbd | ||
|
|
6890805b16 | ||
|
|
c654fdf709 | ||
|
|
c060f4ac3d | ||
|
|
23d3e70b4e | ||
|
|
d945077f42 | ||
|
|
6607ffb9ec | ||
|
|
ad5902bc39 | ||
|
|
5247dc3cd2 | ||
|
|
b340601ef6 | ||
|
|
0f6081ee26 | ||
|
|
c17797f979 | ||
|
|
6638d49ad9 | ||
|
|
659ff22ea4 | ||
|
|
442d78a556 | ||
|
|
a599587fce | ||
|
|
9483255583 | ||
|
|
b3d37a908c | ||
|
|
e039795971 | ||
|
|
47d0f21c60 | ||
|
|
a88d821d9f | ||
|
|
460c4c2b9a | ||
|
|
3bf315d70e | ||
|
|
5d3920f5ab | ||
|
|
69208fc62a | ||
|
|
484a5b38af | ||
|
|
f112083c7a | ||
|
|
2ef148d1ee | ||
|
|
818ef42d22 | ||
|
|
d77b28e90b | ||
|
|
2183e55c12 | ||
|
|
b3d3ae42ed | ||
|
|
61924171bf | ||
|
|
20a081eb37 | ||
|
|
7dbf29a10d | ||
|
|
440543aa88 | ||
|
|
4725941c74 | ||
|
|
f14d0ef339 | ||
|
|
c595c27357 | ||
|
|
6d378bf78e | ||
|
|
23c4d31291 | ||
|
|
6af9f59010 | ||
|
|
571d1f7314 | ||
|
|
dd29092472 | ||
|
|
3a48eef3c8 | ||
|
|
f80da18f2e | ||
|
|
c4c800416f | ||
|
|
a6e4c9210d | ||
|
|
764519245b | ||
|
|
902a15d149 | ||
|
|
3e61ccc2d4 | ||
|
|
3aaf9abb73 | ||
|
|
e348891410 | ||
|
|
45469fbde9 | ||
|
|
0bc349c450 | ||
|
|
6aacfdb9ba | ||
|
|
5aa1c3547e | ||
|
|
c1c31f2cba | ||
|
|
79707ca3ee | ||
|
|
5fcb784294 | ||
|
|
0a1e5eb93b | ||
|
|
826d2ac716 | ||
|
|
878644b358 | ||
|
|
ef4efcced1 | ||
|
|
9e1a44e6bb | ||
|
|
7819816cc9 | ||
|
|
087c4c8b3c | ||
|
|
b370918e0c | ||
|
|
e6ad21933b | ||
|
|
22b96dd414 | ||
|
|
aa2edb427a | ||
|
|
39d6f49896 | ||
|
|
e0a82f4921 | ||
|
|
b95a23ce78 | ||
|
|
7842c19934 | ||
|
|
fef495942a | ||
|
|
b7d480986a | ||
|
|
da6a30b022 | ||
|
|
bca912f91e | ||
|
|
5b77fff586 | ||
|
|
95db5bab42 | ||
|
|
b4c1356d18 | ||
|
|
668dd47700 | ||
|
|
d9bcda01db | ||
|
|
8c50a04455 | ||
|
|
80b849e2a0 | ||
|
|
e15a7d1f7e | ||
|
|
7da8884581 | ||
|
|
871523c8f4 | ||
|
|
09172b112f | ||
|
|
3adc4a6e0e | ||
|
|
b29bf7515b | ||
|
|
cba62feeec | ||
|
|
09c6d53e64 | ||
|
|
78aa706491 | ||
|
|
f50d542ff7 | ||
|
|
583d7205c6 | ||
|
|
1f1dba92a8 | ||
|
|
258e591e45 | ||
|
|
42d27cd152 | ||
|
|
d8d6c7a07b | ||
|
|
4f0163fd38 | ||
|
|
0244879c8f | ||
|
|
743e4c6231 | ||
|
|
c3d99b5292 | ||
|
|
d1f519e0cd | ||
|
|
ff3cec5beb | ||
|
|
b0deadc05d | ||
|
|
ced4ef9ad6 | ||
|
|
ca19ae5ad0 | ||
|
|
9460263e41 | ||
|
|
197ecabb9a | ||
|
|
ee459684f1 | ||
|
|
6516c72ef1 | ||
|
|
9d022818e1 | ||
|
|
b9ae9f5f38 | ||
|
|
b8ac9e1597 | ||
|
|
9537b240de | ||
|
|
9c6de78844 | ||
|
|
6bb4fea31d | ||
|
|
97849a08cd | ||
|
|
2f435912d8 | ||
|
|
d737dc6dd2 | ||
|
|
1b22f12acd | ||
|
|
69bb9e3c8c | ||
|
|
772b5f9a5a | ||
|
|
64acaca8ee | ||
|
|
0008beb1fb | ||
|
|
846b5ea252 | ||
|
|
de0b0b3705 | ||
|
|
4dec99c61e | ||
|
|
18d715b86e | ||
|
|
a157791264 | ||
|
|
590d82bc33 | ||
|
|
a210dacdf4 | ||
|
|
1dfaa528f8 | ||
|
|
8c811778d6 | ||
|
|
395ae75eb3 | ||
|
|
2606966b43 | ||
|
|
c98f0e6631 | ||
|
|
a7714585bb | ||
|
|
da6e4853be | ||
|
|
afba0f3da7 | ||
|
|
d2b947c351 | ||
|
|
d1ba51bc84 | ||
|
|
9d73b2339a | ||
|
|
e88c96b1d7 | ||
|
|
3655e30adb | ||
|
|
112a400662 | ||
|
|
33a9603e93 | ||
|
|
ae6dfa9dae | ||
|
|
c05ae26ec8 | ||
|
|
3b2f29ef69 | ||
|
|
ecb61403d7 | ||
|
|
9eb37bff49 | ||
|
|
605109021f | ||
|
|
a3b7699f42 | ||
|
|
3251460ebd | ||
|
|
ec036ed185 | ||
|
|
5922ea1a0c | ||
|
|
1fb7d64171 | ||
|
|
fd8aa077e3 | ||
|
|
3e8a2aaddb | ||
|
|
c81c29ae58 | ||
|
|
5b4b6e7999 | ||
|
|
f565c92e38 | ||
|
|
fc4bf8158a | ||
|
|
7cd3aa7a1e | ||
|
|
ab4057880e | ||
|
|
d72885b383 | ||
|
|
fd1476e3aa | ||
|
|
142e4ebb57 | ||
|
|
ca92b9104c | ||
|
|
a6179d03f3 | ||
|
|
8afaf0380f | ||
|
|
ca0c409b6f | ||
|
|
177796ff79 | ||
|
|
da3be881ba | ||
|
|
1a0ec77094 | ||
|
|
e226021c5e | ||
|
|
1942c6a035 | ||
|
|
c49166401a | ||
|
|
500c0003b2 | ||
|
|
0275d77fc0 | ||
|
|
67a4b12e27 | ||
|
|
d1c08f11d5 | ||
|
|
40c0867f63 | ||
|
|
7081a85ace |
6
.babelrc
6
.babelrc
@@ -2,8 +2,9 @@
|
||||
"presets": ["react"],
|
||||
"ignore": ["third_party"],
|
||||
"plugins": [
|
||||
"fbjs-scripts/babel-6/dev-expression",
|
||||
"transform-class-properties",
|
||||
"syntax-trailing-function-commas",
|
||||
"transform-object-rest-spread",
|
||||
"transform-es2015-template-literals",
|
||||
"transform-es2015-literals",
|
||||
"transform-es2015-arrow-functions",
|
||||
@@ -21,6 +22,7 @@
|
||||
"transform-es2015-modules-commonjs",
|
||||
"transform-es3-member-expression-literals",
|
||||
"transform-es3-property-literals",
|
||||
"./scripts/babel/transform-object-assign-require"
|
||||
"./scripts/babel/transform-object-assign-require",
|
||||
"transform-react-jsx-source"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# We can probably lint these later but not important at this point
|
||||
src/renderers/art
|
||||
src/shared/vendor
|
||||
# But not in docs/_js/examples/*
|
||||
docs/_js/*.js
|
||||
|
||||
@@ -30,6 +30,7 @@ module.exports = {
|
||||
'indent': [ERROR, 2, {SwitchCase: 1}],
|
||||
'jsx-quotes': [ERROR, 'prefer-double'],
|
||||
'no-bitwise': OFF,
|
||||
'no-inner-declarations': [ERROR, 'functions'],
|
||||
'no-multi-spaces': ERROR,
|
||||
'no-restricted-syntax': [ERROR, 'WithStatement'],
|
||||
'no-shadow': ERROR,
|
||||
|
||||
37
.flowconfig
Normal file
37
.flowconfig
Normal file
@@ -0,0 +1,37 @@
|
||||
[ignore]
|
||||
|
||||
<PROJECT_ROOT>/examples/.*
|
||||
<PROJECT_ROOT>/build/.*
|
||||
<PROJECT_ROOT>/.*/node_modules/y18n/.*
|
||||
<PROJECT_ROOT>/.*/__mocks__/.*
|
||||
<PROJECT_ROOT>/.*/__tests__/.*
|
||||
|
||||
# Ignore Docs
|
||||
<PROJECT_ROOT>/.*/docs/.*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
./node_modules/fbjs/flow/lib
|
||||
./flow
|
||||
|
||||
[options]
|
||||
module.system=haste
|
||||
|
||||
esproposal.class_static_fields=enable
|
||||
esproposal.class_instance_fields=enable
|
||||
|
||||
munge_underscores=false
|
||||
|
||||
suppress_type=$FlowIssue
|
||||
suppress_type=$FlowFixMe
|
||||
suppress_type=$FixMe
|
||||
suppress_type=$FlowExpectedError
|
||||
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-1]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-1]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
|
||||
|
||||
[version]
|
||||
^0.31.0
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,6 +18,7 @@ docs/js/*
|
||||
docs/downloads
|
||||
docs/vendor/bundle
|
||||
examples/shared/*.js
|
||||
examples/**/bundle.js
|
||||
test/the-files-to-test.generated.js
|
||||
*.log*
|
||||
chrome-user-data
|
||||
|
||||
41
.travis.yml
41
.travis.yml
@@ -1,8 +1,11 @@
|
||||
---
|
||||
sudo: required
|
||||
dist: trusty
|
||||
language: node_js
|
||||
node_js:
|
||||
- 4
|
||||
sudo: false
|
||||
rvm:
|
||||
- 2.2.3
|
||||
cache:
|
||||
directories:
|
||||
- docs/vendor/bundle
|
||||
@@ -25,8 +28,8 @@ script:
|
||||
|
||||
GH_PAGES_DIR="$TRAVIS_BUILD_DIR"/../react-gh-pages
|
||||
echo "machine github.com login reactjs-bot password $GITHUB_TOKEN" >~/.netrc
|
||||
git config --global user.name "Travis CI"
|
||||
git config --global user.email "travis@reactjs.org"
|
||||
git config --global user.name "$GITHUB_USER_NAME"
|
||||
git config --global user.email "$GITHUB_USER_EMAIL"
|
||||
|
||||
git clone --branch gh-pages --depth=50 \
|
||||
https://reactjs-bot@github.com/facebook/react.git \
|
||||
@@ -58,6 +61,7 @@ script:
|
||||
-F "react-dom-server.min=@build/react-dom-server.min.js" \
|
||||
-F "npm-react=@build/packages/react.tgz" \
|
||||
-F "npm-react-dom=@build/packages/react-dom.tgz" \
|
||||
-F "npm-react-native=@build/packages/react-native-renderer.tgz" \
|
||||
-F "commit=$TRAVIS_COMMIT" \
|
||||
-F "date=`git log --format='%ct' -1`" \
|
||||
-F "pull_request=$TRAVIS_PULL_REQUEST" \
|
||||
@@ -67,12 +71,40 @@ script:
|
||||
fi
|
||||
elif [ "$TEST_TYPE" = test ]; then
|
||||
set -e
|
||||
./node_modules/.bin/grunt jest:normal
|
||||
./node_modules/.bin/grunt jest:coverage
|
||||
cat ./coverage/lcov.info | ./node_modules/.bin/coveralls
|
||||
|
||||
echo 'Testing in server-render (HTML generation) mode...'
|
||||
printf '\nmodule.exports.useCreateElement = false;\n' \
|
||||
>> src/renderers/dom/shared/ReactDOMFeatureFlags.js
|
||||
./node_modules/.bin/grunt jest:normal
|
||||
git checkout -- src/renderers/dom/shared/ReactDOMFeatureFlags.js
|
||||
|
||||
echo 'Testing in fiber mode...'
|
||||
printf '\nmodule.exports.useFiber = true;\n' \
|
||||
>> src/renderers/dom/shared/ReactDOMFeatureFlags.js
|
||||
FIBER_TESTS=`\
|
||||
NODE_ENV=test node node_modules/jest/bin/jest --json | \
|
||||
node -e "\
|
||||
var data = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8')); \
|
||||
console.log(data.numPassedTests + '/' + data.numTotalTests)\
|
||||
"\
|
||||
`
|
||||
git checkout -- src/renderers/dom/shared/ReactDOMFeatureFlags.js
|
||||
node scripts/facts-tracker/index.js \
|
||||
"fiber-tests" "$FIBER_TESTS"
|
||||
|
||||
./node_modules/.bin/gulp react:extract-errors
|
||||
elif [ "$TEST_TYPE" = flow ]; then
|
||||
set -e
|
||||
./node_modules/.bin/grunt flow
|
||||
|
||||
ALL_FILES=`find src -name '*.js' | grep -v umd/ | grep -v __tests__ | grep -v __mocks__`
|
||||
COUNT_ALL_FILES=`echo "$ALL_FILES" | wc -l`
|
||||
COUNT_WITH_FLOW=`grep '@flow' $ALL_FILES | perl -pe 's/:.+//' | wc -l`
|
||||
node scripts/facts-tracker/index.js \
|
||||
"flow-files" "$COUNT_WITH_FLOW/$COUNT_ALL_FILES"
|
||||
|
||||
else
|
||||
./node_modules/.bin/grunt $TEST_TYPE
|
||||
fi
|
||||
@@ -81,6 +113,7 @@ env:
|
||||
- TEST_TYPE=build
|
||||
- TEST_TYPE=test
|
||||
- TEST_TYPE=lint
|
||||
- TEST_TYPE=flow
|
||||
- TEST_TYPE=build_website
|
||||
global:
|
||||
# SERVER
|
||||
|
||||
299
CHANGELOG.md
299
CHANGELOG.md
@@ -1,3 +1,294 @@
|
||||
## 15.3.2 (September 19, 2016)
|
||||
|
||||
### React
|
||||
- Remove plain object warning from React.createElement & React.cloneElement. ([@spudly](https://github.com/spudly) in [#7724](https://github.com/facebook/react/pull/7724))
|
||||
|
||||
### React DOM
|
||||
- Add `playsInline` to supported HTML attributes. ([@reaperhulk](https://github.com/reaperhulk) in [#7519](https://github.com/facebook/react/pull/7519))
|
||||
- Add `as` to supported HTML attributes. ([@kevinslin](https://github.com/kevinslin) in [#7582](https://github.com/facebook/react/pull/7582))
|
||||
- Improve DOM nesting validation warning about whitespace. ([@spicyj](https://github.com/spicyj) in [#7515](https://github.com/facebook/react/pull/7515))
|
||||
- Avoid "Member not found" exception in IE10 when calling `preventDefault()` in Synthetic Events. ([@g-palmer](https://github.com/g-palmer) in [#7411](https://github.com/facebook/react/pull/7411))
|
||||
- Fix memory leak in `onSelect` implementation. ([@AgtLucas](https://github.com/AgtLucas) in [#7533](https://github.com/facebook/react/pull/7533))
|
||||
- Improve robustness of `document.documentMode` checks to handle Google Tag Manager. ([@SchleyB](https://github.com/SchleyB) in [#7594](https://github.com/facebook/react/pull/7594))
|
||||
- Add more cases to controlled inputs warning. ([@marcin-mazurek](https://github.com/marcin-mazurek) in [#7544](https://github.com/facebook/react/pull/7544))
|
||||
- Handle case of popup blockers overriding `document.createEvent`. ([@Andarist](https://github.com/Andarist) in [#7621](https://github.com/facebook/react/pull/7621))
|
||||
- Fix issue with `dangerouslySetInnerHTML` and SVG in Internet Explorer. ([@zpao](https://github.com/zpao) in [#7618](https://github.com/facebook/react/pull/7618))
|
||||
- Improve handling of Japanese IME on Internet Explorer. ([@msmania](https://github.com/msmania) in [#7107](https://github.com/facebook/react/pull/7107))
|
||||
|
||||
### React Test Renderer
|
||||
- Support error boundaries. ([@millermedeiros](https://github.com/millermedeiros) in [#7558](https://github.com/facebook/react/pull/7558), [#7569](https://github.com/facebook/react/pull/7569), [#7619](https://github.com/facebook/react/pull/7619))
|
||||
- Skip null ref warning. ([@Aweary](https://github.com/Aweary) in [#7658](https://github.com/facebook/react/pull/7658))
|
||||
|
||||
### React Perf Add-on
|
||||
- Ensure lifecycle timers are stopped on errors. ([@gaearon](https://github.com/gaearon) in [#7548](https://github.com/facebook/react/pull/7548))
|
||||
|
||||
|
||||
## 15.3.1 (August 19, 2016)
|
||||
|
||||
### React
|
||||
|
||||
- Improve performance of development builds in various ways. ([@gaearon](https://github.com/gaearon) in [#7461](https://github.com/facebook/react/pull/7461), [#7463](https://github.com/facebook/react/pull/7463), [#7483](https://github.com/facebook/react/pull/7483), [#7488](https://github.com/facebook/react/pull/7488), [#7491](https://github.com/facebook/react/pull/7491), [#7510](https://github.com/facebook/react/pull/7510))
|
||||
- Cleanup internal hooks to improve performance of development builds. ([@gaearon](https://github.com/gaearon) in [#7464](https://github.com/facebook/react/pull/7464), [#7472](https://github.com/facebook/react/pull/7472), [#7481](https://github.com/facebook/react/pull/7481), [#7496](https://github.com/facebook/react/pull/7496))
|
||||
- Upgrade fbjs to pick up another performance improvement from [@gaearon](https://github.com/gaearon) for development builds. ([@zpao](https://github.com/zpao) in [#7532](https://github.com/facebook/react/pull/7532))
|
||||
- Improve startup time of React in Node. ([@zertosh](https://github.com/zertosh) in [#7493](https://github.com/facebook/react/pull/7493))
|
||||
- Improve error message of `React.Children.only`. ([@spicyj](https://github.com/spicyj) in [#7514](https://github.com/facebook/react/pull/7514))
|
||||
|
||||
### React DOM
|
||||
- Avoid `<input>` validation warning from browsers when changing `type`. ([@nhunzaker](https://github.com/nhunzaker) in [#7333](https://github.com/facebook/react/pull/7333))
|
||||
- Avoid "Member not found" exception in IE10 when calling `stopPropagation()` in Synthetic Events. ([@nhunzaker](https://github.com/nhunzaker) in [#7343](https://github.com/facebook/react/pull/7343))
|
||||
- Fix issue resulting in inability to update some `<input>` elements in mobile browsers. ([@keyanzhang](https://github.com/keyanzhang) in [#7397](https://github.com/facebook/react/pull/7397))
|
||||
- Fix memory leak in server rendering. ([@keyanzhang](https://github.com/keyanzhang) in [#7410](https://github.com/facebook/react/pull/7410))
|
||||
- Fix issue resulting in `<input type="range">` values not updating when changing `min` or `max`. ([@troydemonbreun](https://github.com/troydemonbreun) in [#7486](https://github.com/facebook/react/pull/7486))
|
||||
- Add new warning for rare case of attempting to unmount a container owned by a different copy of React. ([@ventuno](https://github.com/ventuno) in [#7456](https://github.com/facebook/react/pull/7456))
|
||||
|
||||
### React Test Renderer
|
||||
- Fix ReactTestInstance::toJSON() with empty top-level components. ([@Morhaus](https://github.com/Morhaus) in [#7523](https://github.com/facebook/react/pull/7523))
|
||||
|
||||
### React Native Renderer
|
||||
- Change `trackedTouchCount` invariant into a console.error for better reliability. ([@yungsters](https://github.com/yungsters) in [#7400](https://github.com/facebook/react/pull/7400))
|
||||
|
||||
|
||||
## 15.3.0 (July 29, 2016)
|
||||
|
||||
### React
|
||||
- Add `React.PureComponent` - a new base class to extend, replacing `react-addons-pure-render-mixin` now that mixins don't work with ES2015 classes. ([@spicyj](https://github.com/spicyj) in [#7195](https://github.com/facebook/react/pull/7195))
|
||||
- Add new warning when modifying `this.props.children`. ([@jimfb](https://github.com/jimfb) in [#7001](https://github.com/facebook/react/pull/7001))
|
||||
- Fixed issue with ref resolution order. ([@gaearon](https://github.com/gaearon) in [#7101](https://github.com/facebook/react/pull/7101))
|
||||
- Warn when mixin is undefined. ([@swaroopsm](https://github.com/swaroopsm) in [#6158](https://github.com/facebook/react/pull/6158))
|
||||
- Downgrade "unexpected batch number" invariant to a warning. ([@spicyj](https://github.com/spicyj) in [#7133](https://github.com/facebook/react/pull/7133))
|
||||
- Validate arguments to `oneOf` and `oneOfType` PropTypes sooner. ([@troydemonbreun](https://github.com/troydemonbreun) in [#6316](https://github.com/facebook/react/pull/6316))
|
||||
- Warn when calling PropTypes directly. ([@Aweary](https://github.com/Aweary) in [#7132](https://github.com/facebook/react/pull/7132), [#7194](https://github.com/facebook/react/pull/7194))
|
||||
- Improve warning when using Maps as children. ([@keyanzhang](https://github.com/keyanzhang) in [#7260](https://github.com/facebook/react/pull/7260))
|
||||
- Add additional type information to the `PropTypes.element` warning. ([@alexzherdev](https://github.com/alexzherdev) in [#7319](https://github.com/facebook/react/pull/7319))
|
||||
- Improve component identification in no-op `setState` warning. ([@keyanzhang](https://github.com/keyanzhang) in [#7326](https://github.com/facebook/react/pull/7326))
|
||||
|
||||
### React DOM
|
||||
- Fix issue with nested server rendering. ([@Aweary](https://github.com/Aweary) in [#7033](https://github.com/facebook/react/pull/7033))
|
||||
- Add `xmlns`, `xmlnsXlink` to supported SVG attributes. ([@salzhrani](https://github.com/salzhrani) in [#6471](https://github.com/facebook/react/pull/6471))
|
||||
- Add `referrerPolicy` to supported HTML attributes. ([@Aweary](https://github.com/Aweary) in [#7274](https://github.com/facebook/react/pull/7274))
|
||||
- Fix issue resulting in `<input type="range">` initial value being rounded. ([@troydemonbreun](https://github.com/troydemonbreun) in [#7251](https://github.com/facebook/react/pull/7251))
|
||||
|
||||
### React Test Renderer
|
||||
- Initial public release of package allowing more focused testing. Install with `npm install react-test-renderer`. ([@spicyj](https://github.com/spicyj) in [#6944](https://github.com/facebook/react/pull/6944), [#7258](https://github.com/facebook/react/pull/7258), [@iamdustan](https://github.com/iamdustan) in [#7362](https://github.com/facebook/react/pull/7362))
|
||||
|
||||
### React Perf Add-on
|
||||
- Fix issue resulting in excessive warnings when encountering an internal measurement error. ([@sassanh](https://github.com/sassanh) in [#7299](https://github.com/facebook/react/pull/7299))
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Implement `type` property on for events created via `TestUtils.Simulate.*`. ([@yaycmyk](https://github.com/yaycmyk) in [#6154](https://github.com/facebook/react/pull/6154))
|
||||
- Fix crash when running TestUtils with the production build of React. ([@gaearon](https://github.com/gaearon) in [#7246](https://github.com/facebook/react/pull/7246))
|
||||
|
||||
|
||||
## 15.2.1 (July 8, 2016)
|
||||
|
||||
### React
|
||||
- Fix errant warning about missing React element. ([@gaearon](https://github.com/gaearon) in [#7193](https://github.com/facebook/react/pull/7193))
|
||||
- Better removal of dev-only code, leading to a small reduction in the minified production bundle size. ([@gaearon](https://github.com/gaearon) in [#7188](https://github.com/facebook/react/pull/7188), [#7189](https://github.com/facebook/react/pull/7189))
|
||||
|
||||
### React DOM
|
||||
- Add stack trace to null input value warning. ([@jimfb](https://github.com/jimfb) in [#7040](https://github.com/facebook/react/pull/7040))
|
||||
- Fix webcomponents example. ([@jalexanderfox](https://github.com/jalexanderfox) in [#7057](https://github.com/facebook/react/pull/7057))
|
||||
- Fix `unstable_renderSubtreeIntoContainer` so that context properly updates when linked to state. ([@gaearon](https://github.com/gaearon) in [#7125](https://github.com/facebook/react/pull/7125))
|
||||
- Improve invariant wording for void elements. ([@starkch](https://github.com/starkch) in [#7066](https://github.com/facebook/react/pull/7066))
|
||||
- Ensure no errors are thrown due to event handlers in server rendering. ([@rricard](https://github.com/rricard) in [#7127](https://github.com/facebook/react/pull/7127))
|
||||
- Fix regression resulting in `value`-less submit and reset inputs removing the browser-default text. ([@zpao](https://github.com/zpao) in [#7197](https://github.com/facebook/react/pull/7197))
|
||||
- Fix regression resulting in empty `name` attribute being added to inputs when not provided. ([@okonet](https://github.com/okonet) in [#7199](https://github.com/facebook/react/pull/7199))
|
||||
- Fix issue with nested server rendering. ([@Aweary](https://github.com/Aweary) in [#7033](https://github.com/facebook/react/pull/7033))
|
||||
|
||||
### React Perf Add-on
|
||||
- Make `ReactPerf.start()` work properly during lifecycle methods. ([@gaearon](https://github.com/gaearon) in [#7208](https://github.com/facebook/react/pull/7208)).
|
||||
|
||||
### React CSSTransitionGroup Add-on
|
||||
- Fix issue resulting in spurious unknown property warnings. ([@batusai513](https://github.com/batusai513) in [#7165](https://github.com/facebook/react/pull/7165))
|
||||
|
||||
### React Native Renderer
|
||||
- Improve error handling in cross-platform touch event handling. ([@yungsters](https://github.com/yungsters) in [#7143](https://github.com/facebook/react/pull/7143))
|
||||
|
||||
|
||||
## 15.2.0 (July 1, 2016)
|
||||
|
||||
### React
|
||||
- Add error codes to production invariants, with links to the view the full error text. ([@keyanzhang](https://github.com/keyanzhang) in [#6948](https://github.com/facebook/react/pull/6948))
|
||||
- Include component stack information in PropType validation warnings. ([@troydemonbreun](https://github.com/troydemonbreun) in [#6398](https://github.com/facebook/react/pull/6398), [@spicyj](https://github.com/spicyj) in [#6771](https://github.com/facebook/react/pull/6771))
|
||||
- Include component stack information in key warnings. ([@keyanzhang](https://github.com/keyanzhang) in [#6799](https://github.com/facebook/react/pull/6799))
|
||||
- Stop validating props at mount time, only validate at element creation. ([@keyanzhang](https://github.com/keyanzhang) in [#6824](https://github.com/facebook/react/pull/6824))
|
||||
- New invariant providing actionable error in missing instance case. ([@yungsters](https://github.com/yungsters) in [#6990](https://github.com/facebook/react/pull/6990))
|
||||
- Add `React.PropTypes.symbol` to support ES2015 Symbols as props. ([@puradox](https://github.com/puradox) in [#6377](https://github.com/facebook/react/pull/6377))
|
||||
- Fix incorrect coercion of ref or key that are undefined in development ([@gaearon](https://github.com/gaearon) in [#6880](https://github.com/facebook/react/pull/6880))
|
||||
- Fix a false positive when passing other element’s props to cloneElement ([@ericmatthys](https://github.com/ericmatthys) in [#6268](https://github.com/facebook/react/pull/6268))
|
||||
- Warn if you attempt to define `childContextTypes` on a functional component ([@Aweary](https://github.com/Aweary) in [#6933](https://github.com/facebook/react/pull/6933))
|
||||
|
||||
### React DOM
|
||||
- Add warning for unknown properties on DOM elements. ([@jimfb](https://github.com/jimfb) in [#6800](https://github.com/facebook/react/pull/6800), [@gm758](https://github.com/gm758) in [#7152](https://github.com/facebook/react/pull/7152))
|
||||
- Properly remove attributes from custom elements. ([@grassator](https://github.com/grassator) in [#6748](https://github.com/facebook/react/pull/6748))
|
||||
- Fix invalid unicode escape in attribute name regular expression. ([@nbjahan](https://github.com/nbjahan) in [#6772](https://github.com/facebook/react/pull/6772))
|
||||
- Add `onLoad` handling to `<link>` element. ([@roderickhsiao](https://github.com/roderickhsiao) in [#6815](https://github.com/facebook/react/pull/6815))
|
||||
- Add `onError` handling to `<source>` element. ([@wadahiro](https://github.com/wadahiro) in [#6941](https://github.com/facebook/react/pull/6941))
|
||||
- Handle `value` and `defaultValue` more accurately in the DOM. ([@jimfb](https://github.com/jimfb) in [#6406](https://github.com/facebook/react/pull/6406))
|
||||
- Fix events issue in environments with mutated `Object.prototype`. ([@Weizenlol](https://github.com/Weizenlol) in [#6886](https://github.com/facebook/react/pull/6886))
|
||||
- Fix issue where `is="null"` ended up in the DOM in Firefox. ([@darobin](https://github.com/darobin) in [#6896](https://github.com/facebook/react/pull/6896))
|
||||
- Improved performance of text escaping by using [escape-html](https://github.com/component/escape-html). ([@aickin](https://github.com/aickin) in [#6862](https://github.com/facebook/react/pull/6862))
|
||||
- Fix issue with `dangerouslySetInnerHTML` and SVG in Internet Explorer. ([@joshhunt](https://github.com/joshhunt) in [#6982](https://github.com/facebook/react/pull/6982))
|
||||
- Fix issue with `<textarea>` placeholders. ([@jimfb](https://github.com/jimfb) in [#7002](https://github.com/facebook/react/pull/7002))
|
||||
- Fix controlled vs uncontrolled detection of `<input type="radio"/>`. ([@jimfb](https://github.com/jimfb) in [#7003](https://github.com/facebook/react/pull/7003))
|
||||
- Improve performance of updating text content. ([@trueadm](https://github.com/trueadm) in [#7005](https://github.com/facebook/react/pull/7005))
|
||||
- Ensure controlled `<select>` components behave the same on initial render as they do on updates. ([@yiminghe](https://github.com/yiminghe) in [#5362](https://github.com/facebook/react/pull/5362))
|
||||
|
||||
### React Perf Add-on
|
||||
- Add `isRunning()` API. ([@nfcampos](https://github.com/nfcampos) in [#6763](https://github.com/facebook/react/pull/6763))
|
||||
- Improve accuracy of lifecycle hook timing. ([@gaearon](https://github.com/gaearon) in [#6858](https://github.com/facebook/react/pull/6858))
|
||||
- Fix internal errors when using ReactPerf with portal components. ([@gaearon](https://github.com/gaearon) in [#6860](https://github.com/facebook/react/pull/6860))
|
||||
- Fix performance regression. ([@spicyj](https://github.com/spicyj) in [#6770](https://github.com/facebook/react/pull/6770))
|
||||
- Add warning that ReactPerf is not enabled in production. ([@sashashakun](https://github.com/sashashakun) in [#6884](https://github.com/facebook/react/pull/6884))
|
||||
|
||||
### React CSSTransitionGroup Add-on
|
||||
- Fix timing issue with `null` node. ([@keyanzhang](https://github.com/keyanzhang) in [#6958](https://github.com/facebook/react/pull/6958))
|
||||
|
||||
### React Native Renderer
|
||||
- Dependencies on React Native modules use CommonJS requires instead of providesModule. ([@davidaurelio](https://github.com/davidaurelio) in [#6715](https://github.com/facebook/react/pull/6715))
|
||||
|
||||
|
||||
## 15.1.0 (May 20, 2016)
|
||||
|
||||
### React
|
||||
- Ensure we're using the latest `object-assign`, which has protection against a non-spec-compliant native `Object.assign`. ([@zpao](https://github.com/zpao) in [#6681](https://github.com/facebook/react/pull/6681))
|
||||
- Add a new warning to communicate that `props` objects passed to `createElement` must be plain objects. ([@richardscarrott](https://github.com/richardscarrott) in [#6134](https://github.com/facebook/react/pull/6134))
|
||||
- Fix a batching bug resulting in some lifecycle methods incorrectly being called multiple times. ([@spicyj](https://github.com/spicyj) in [#6650](https://github.com/facebook/react/pull/6650))
|
||||
|
||||
### React DOM
|
||||
- Fix regression in custom elements support. ([@jscissr](https://github.com/jscissr) in [#6570](https://github.com/facebook/react/pull/6570))
|
||||
- Stop incorrectly warning about using `onScroll` event handler with server rendering. ([@Aweary](https://github.com/Aweary) in [#6678](https://github.com/facebook/react/pull/6678))
|
||||
- Fix grammar in the controlled input warning. ([@jakeboone02](https://github.com/jakeboone02) in [#6657](https://github.com/facebook/react/pull/6657))
|
||||
- Fix issue preventing `<object>` nodes from being able to read `<param>` nodes in IE. ([@syranide](https://github.com/syranide) in [#6691](https://github.com/facebook/react/pull/6691))
|
||||
- Fix issue resulting in crash when using experimental error boundaries with server rendering. ([@jimfb](https://github.com/jimfb) in [#6694](https://github.com/facebook/react/pull/6694))
|
||||
- Add additional information to the controlled input warning. ([@borisyankov](https://github.com/borisyankov) in [#6341](https://github.com/facebook/react/pull/6341))
|
||||
|
||||
### React Perf Add-on
|
||||
- Completely rewritten to collect data more accurately and to be easier to maintain. ([@gaearon](https://github.com/gaearon) in [#6647](https://github.com/facebook/react/pull/6647), [#6046](https://github.com/facebook/react/pull/6046))
|
||||
|
||||
### React Native Renderer
|
||||
- Remove some special cases for platform specific branching. ([@sebmarkbage](https://github.com/sebmarkbage) in [#6660](https://github.com/facebook/react/pull/6660))
|
||||
- Remove use of `merge` utility. ([@sebmarkbage](https://github.com/sebmarkbage) in [#6634](https://github.com/facebook/react/pull/6634))
|
||||
- Renamed some modules to better indicate usage ([@javache](https://github.com/javache) in [#6643](https://github.com/facebook/react/pull/6643))
|
||||
|
||||
|
||||
## 15.0.2 (April 29, 2016)
|
||||
|
||||
### React
|
||||
- Removed extraneous files from npm package. ([@gaearon](https://github.com/gaearon) in [#6388](https://github.com/facebook/react/pull/6388))
|
||||
- Ensure `componentWillUnmount` is only called once. ([@jimfb](https://github.com/jimfb) in [#6613](https://github.com/facebook/react/pull/6613))
|
||||
|
||||
### ReactDOM
|
||||
- Fixed bug resulting in disabled buttons responding to mouse events in IE. ([@nhunzaker](https://github.com/nhunzaker) in [#6215](https://github.com/facebook/react/pull/6215))
|
||||
- Ensure `<option>`s are correctly selected when inside `<optgroup>`. ([@trevorsmith](https://github.com/trevorsmith) in [#6442](https://github.com/facebook/react/pull/6442))
|
||||
- Restore support for rendering into a shadow root. ([@Wildhoney](https://github.com/Wildhoney) in [#6462](https://github.com/facebook/react/pull/6462))
|
||||
- Ensure nested `<body>` elements are caught when warning for invalid markup. ([@keyanzhang](https://github.com/keyanzhang) in [#6469](https://github.com/facebook/react/pull/6469))
|
||||
- Improve warning when encountering multiple elements with the same key. ([@hkal](https://github.com/hkal) in [#6500](https://github.com/facebook/react/pull/6500))
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Ensure that functional components do not have an owner. ([@gaearon](https://github.com/gaearon) in [#6362](https://github.com/facebook/react/pull/6362))
|
||||
- Handle invalid arguments to `scryRenderedDOMComponentsWithClass` better. ([@ipeters90](https://github.com/ipeters90) in [#6529](https://github.com/facebook/react/pull/6529))
|
||||
|
||||
### React Perf Add-on
|
||||
- Ignore DOM operations that occur outside the batch operation. ([@gaearon](https://github.com/gaearon) in [#6516](https://github.com/facebook/react/pull/6516))
|
||||
|
||||
### React Native Renderer
|
||||
- These files are now shipped inside the React npm package. They have no impact on React core or ReactDOM.
|
||||
|
||||
|
||||
## 15.0.1 (April 8, 2016)
|
||||
|
||||
### React
|
||||
- Restore `React.__spread` API to unbreak code compiled with some tools making use of this undocumented API. It is now officially deprecated. ([@zpao](https://github.com/zpao) in [#6444](https://github.com/facebook/react/pull/6444))
|
||||
|
||||
### ReactDOM
|
||||
- Fixed issue resulting in loss of cursor position in controlled inputs. ([@spicyj](https://github.com/spicyj) in [#6449](https://github.com/facebook/react/pull/6449))
|
||||
|
||||
|
||||
## 15.0.0 (April 7, 2016)
|
||||
|
||||
### Major changes
|
||||
|
||||
- **Initial render now uses `document.createElement` instead of generating HTML.** Previously we would generate a large string of HTML and then set `node.innerHTML`. At the time, this was decided to be faster than using `document.createElement` for the majority of cases and browsers that we supported. Browsers have continued to improve and so overwhelmingly this is no longer true. By using `createElement` we can make other parts of React faster. ([@spicyj](https://github.com/spicyj) in [#5205](https://github.com/facebook/react/pull/5205))
|
||||
- **`data-reactid` is no longer on every node.** As a result of using `document.createElement`, we can prime the node cache as we create DOM nodes, allowing us to skip a potential lookup (which used the `data-reactid` attribute). Root nodes will have a `data-reactroot` attribute and server generated markup will still contain `data-reactid`. ([@spicyj](https://github.com/spicyj) in [#5205](https://github.com/facebook/react/pull/5205))
|
||||
- **No more extra `<span>`s.** ReactDOM will now render plain text nodes interspersed with comment nodes that are used for demarcation. This gives us the same ability to update individual pieces of text, without creating extra nested nodes. If you were targeting these `<span>`s in your CSS, you will need to adjust accordingly. You can always render them explicitly in your components. ([@mwiencek](https://github.com/mwiencek) in [#5753](https://github.com/facebook/react/pull/5753))
|
||||
- **Rendering `null` now uses comment nodes.** Previously `null` would render to `<noscript>` elements. We now use comment nodes. This may cause issues if making use of `:nth-child` CSS selectors. While we consider this rendering behavior an implementation detail of React, it's worth noting the potential problem. ()[@spicyj](https://github.com/spicyj) in [#5451](https://github.com/facebook/react/pull/5451))
|
||||
- **Functional components can now return `null`.** We added support for [defining stateless components as functions](/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components) in React 0.14. However, React 0.14 still allowed you to define a class component without extending `React.Component` or using `React.createClass()`, so [we couldn’t reliably tell if your component is a function or a class](https://github.com/facebook/react/issues/5355), and did not allow returning `null` from it. This issue is solved in React 15, and you can now return `null` from any component, whether it is a class or a function. ([@jimfb](https://github.com/jimfb) in [#5884](https://github.com/facebook/react/pull/5884))
|
||||
- **Improved SVG support.** All SVG tags are now fully supported. (Uncommon SVG tags are not present on the `React.DOM` element helper, but JSX and `React.createElement` work on all tag names.) All SVG attributes that are implemented by the browsers should be supported too. If you find any attributes that we have missed, please [let us know in this issue](https://github.com/facebook/react/issues/1657). ([@zpao](https://github.com/zpao) in [#6243](https://github.com/facebook/react/pull/6243))
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- **No more extra `<span>`s.**
|
||||
- **`React.cloneElement()` now resolves `defaultProps`.** We fixed a bug in `React.cloneElement()` that some components may rely on. If some of the `props` received by `cloneElement()` are `undefined`, it used to return an element with `undefined` values for those props. We’re changing it to be consistent with `createElement()`. Now any `undefined` props passed to `cloneElement()` are resolved to the corresponding component’s `defaultProps`. ([@truongduy134](https://github.com/truongduy134) in [#5997](https://github.com/facebook/react/pull/5997))
|
||||
- **`ReactPerf.getLastMeasurements()` is opaque.** This change won’t affect applications but may break some third-party tools. We are [revamping `ReactPerf` implementation](https://github.com/facebook/react/pull/6046) and plan to release it during the 15.x cycle. The internal performance measurement format is subject to change so, for the time being, we consider the return value of `ReactPerf.getLastMeasurements()` an opaque data structure that should not be relied upon. ([@gaearon](https://github.com/gaearon) in [#6286](https://github.com/facebook/react/pull/6286))
|
||||
|
||||
#### Removed deprecations
|
||||
|
||||
These deprecations were introduced nine months ago in v0.14 with a warning and are removed:
|
||||
|
||||
- Deprecated APIs are removed from the `React` top-level export: `findDOMNode`, `render`, `renderToString`, `renderToStaticMarkup`, and `unmountComponentAtNode`. As a reminder, they are now available on `ReactDOM` and `ReactDOMServer`. ([@jimfb](https://github.com/jimfb) in [#5832](https://github.com/facebook/react/pull/5832))
|
||||
- Deprecated addons are removed: `batchedUpdates` and `cloneWithProps`. ([@jimfb](https://github.com/jimfb) in [#5859](https://github.com/facebook/react/pull/5859), [@zpao](https://github.com/zpao) in [#6016](https://github.com/facebook/react/pull/6016))
|
||||
- Deprecated component instance methods are removed: `setProps`, `replaceProps`, and `getDOMNode`. ([@jimfb](https://github.com/jimfb) in [#5570](https://github.com/facebook/react/pull/5570))
|
||||
- Deprecated CommonJS `react/addons` entry point is removed. As a reminder, you should use separate `react-addons-*` packages instead. This only applies if you use the CommonJS builds. ([@gaearon](https://github.com/gaearon) in [#6285](https://github.com/facebook/react/pull/6285))
|
||||
- Passing `children` to void elements like `<input>` was deprecated, and now throws an error. ([@jonhester](https://github.com/jonhester) in [#3372](https://github.com/facebook/react/pull/3372))
|
||||
- React-specific properties on DOM `refs` (e.g. `this.refs.div.props`) were deprecated, and are removed now. ([@jimfb](https://github.com/jimfb) in [#5495](https://github.com/facebook/react/pull/5495))
|
||||
|
||||
### New deprecations, introduced with a warning
|
||||
|
||||
Each of these changes will continue to work as before with a new warning until the release of React 16 so you can upgrade your code gradually.
|
||||
|
||||
- `LinkedStateMixin` and `valueLink` are now deprecated due to very low popularity. If you need this, you can use a wrapper component that implements the same behavior: [react-linked-input](https://www.npmjs.com/package/react-linked-input). ([@jimfb](https://github.com/jimfb) in [#6127](https://github.com/facebook/react/pull/6127))
|
||||
- Future versions of React will treat `<input value={null}>` as a request to clear the input. However, React 0.14 has been ignoring `value={null}`. React 15 warns you on a `null` input value and offers you to clarify your intention. To fix the warning, you may explicitly pass an empty string to clear a controlled input, or pass `undefined` to make the input uncontrolled. ([@antoaravinth](https://github.com/antoaravinth) in [#5048](https://github.com/facebook/react/pull/5048))
|
||||
- `ReactPerf.printDOM()` was renamed to `ReactPerf.printOperations()`, and `ReactPerf.getMeasurementsSummaryMap()` was renamed to `ReactPerf.getWasted()`. ([@gaearon](https://github.com/gaearon) in [#6287](https://github.com/facebook/react/pull/6287))
|
||||
|
||||
### New helpful warnings
|
||||
|
||||
- If you use a minified copy of the _development_ build, React DOM kindly encourages you to use the faster production build instead. ([@spicyj](https://github.com/spicyj) in [#5083](https://github.com/facebook/react/pull/5083))
|
||||
- React DOM: When specifying a unit-less CSS value as a string, a future version will not add `px` automatically. This version now warns in this case (ex: writing `style={{'{{'}}width: '300'}}`. Unitless *number* values like `width: 300` are unchanged. ([@pluma](https://github.com/pluma) in [#5140](https://github.com/facebook/react/pull/5140))
|
||||
- Synthetic Events will now warn when setting and accessing properties (which will not get cleared appropriately), as well as warn on access after an event has been returned to the pool. ([@kentcdodds](https://github.com/kentcdodds) in [#5940](https://github.com/facebook/react/pull/5940) and [@koba04](https://github.com/koba04) in [#5947](https://github.com/facebook/react/pull/5947))
|
||||
- Elements will now warn when attempting to read `ref` and `key` from the props. ([@prometheansacrifice](https://github.com/prometheansacrifice) in [#5744](https://github.com/facebook/react/pull/5744))
|
||||
- React will now warn if you pass a different `props` object to `super()` in the constructor. ([@prometheansacrifice](https://github.com/prometheansacrifice) in [#5346](https://github.com/facebook/react/pull/5346))
|
||||
- React will now warn if you call `setState()` inside `getChildContext()`. ([@raineroviir](https://github.com/raineroviir) in [#6121](https://github.com/facebook/react/pull/6121))
|
||||
- React DOM now attempts to warn for mistyped event handlers on DOM elements, such as `onclick` which should be `onClick`. ([@ali](https://github.com/ali) in [#5361](https://github.com/facebook/react/pull/5361))
|
||||
- React DOM now warns about `NaN` values in `style`. ([@jontewks](https://github.com/jontewks) in [#5811](https://github.com/facebook/react/pull/5811))
|
||||
- React DOM now warns if you specify both `value` and `defaultValue` for an input. ([@mgmcdermott](https://github.com/mgmcdermott) in [#5823](https://github.com/facebook/react/pull/5823))
|
||||
- React DOM now warns if an input switches between being controlled and uncontrolled. ([@TheBlasfem](https://github.com/TheBlasfem) in [#5864](https://github.com/facebook/react/pull/5864))
|
||||
- React DOM now warns if you specify `onFocusIn` or `onFocusOut` handlers as they are unnecessary in React. ([@jontewks](https://github.com/jontewks) in [#6296](https://github.com/facebook/react/pull/6296))
|
||||
- React now prints a descriptive error message when you pass an invalid callback as the last argument to `ReactDOM.render()`, `this.setState()`, or `this.forceUpdate()`. ([@conorhastings](https://github.com/conorhastings) in [#5193](https://github.com/facebook/react/pull/5193) and [@gaearon](https://github.com/gaearon) in [#6310](https://github.com/facebook/react/pull/6310))
|
||||
- Add-Ons: `TestUtils.Simulate()` now prints a helpful message if you attempt to use it with shallow rendering. ([@conorhastings](https://github.com/conorhastings) in [#5358](https://github.com/facebook/react/pull/5358))
|
||||
- PropTypes: `arrayOf()` and `objectOf()` provide better error messages for invalid arguments. ([@chicoxyzzy](https://github.com/chicoxyzzy) in [#5390](https://github.com/facebook/react/pull/5390))
|
||||
|
||||
### Notable bug fixes
|
||||
|
||||
- Fixed multiple small memory leaks. ([@spicyj](https://github.com/spicyj) in [#4983](https://github.com/facebook/react/pull/4983) and [@victor-homyakov](https://github.com/victor-homyakov) in [#6309](https://github.com/facebook/react/pull/6309))
|
||||
- Input events are handled more reliably in IE 10 and IE 11; spurious events no longer fire when using a placeholder. ([@jquense](https://github.com/jquense) in [#4051](https://github.com/facebook/react/pull/4051))
|
||||
- The `componentWillReceiveProps()` lifecycle method is now consistently called when `context` changes. ([@milesj](https://github.com/milesj) in [#5787](https://github.com/facebook/react/pull/5787))
|
||||
- `React.cloneElement()` doesn’t append slash to an existing `key` when used inside `React.Children.map()`. ([@ianobermiller](https://github.com/ianobermiller) in [#5892](https://github.com/facebook/react/pull/5892))
|
||||
- React DOM now supports the `cite` and `profile` HTML attributes. ([@AprilArcus](https://github.com/AprilArcus) in [#6094](https://github.com/facebook/react/pull/6094) and [@saiichihashimoto](https://github.com/saiichihashimoto) in [#6032](https://github.com/facebook/react/pull/6032))
|
||||
- React DOM now supports `cssFloat`, `gridRow` and `gridColumn` CSS properties. ([@stevenvachon](https://github.com/stevenvachon) in [#6133](https://github.com/facebook/react/pull/6133) and [@mnordick](https://github.com/mnordick) in [#4779](https://github.com/facebook/react/pull/4779))
|
||||
- React DOM now correctly handles `borderImageOutset`, `borderImageWidth`, `borderImageSlice`, `floodOpacity`, `strokeDasharray`, and `strokeMiterlimit` as unitless CSS properties. ([@rofrischmann](https://github.com/rofrischmann) in [#6210](https://github.com/facebook/react/pull/6210) and [#6270](https://github.com/facebook/react/pull/6270))
|
||||
- React DOM now supports the `onAnimationStart`, `onAnimationEnd`, `onAnimationIteration`, `onTransitionEnd`, and `onInvalid` events. Support for `onLoad` has been added to `object` elements. ([@tomduncalf](https://github.com/tomduncalf) in [#5187](https://github.com/facebook/react/pull/5187), [@milesj](https://github.com/milesj) in [#6005](https://github.com/facebook/react/pull/6005), and [@ara4n](https://github.com/ara4n) in [#5781](https://github.com/facebook/react/pull/5781))
|
||||
- React DOM now defaults to using DOM attributes instead of properties, which fixes a few edge case bugs. Additionally the nullification of values (ex: `href={null}`) now results in the forceful removal, no longer trying to set to the default value used by browsers in the absence of a value. ([@syranide](https://github.com/syranide) in [#1510](https://github.com/facebook/react/pull/1510))
|
||||
- React DOM does not mistakingly coerce `children` to strings for Web Components. ([@jimfb](https://github.com/jimfb) in [#5093](https://github.com/facebook/react/pull/5093))
|
||||
- React DOM now correctly normalizes SVG `<use>` events. ([@edmellum](https://github.com/edmellum) in [#5720](https://github.com/facebook/react/pull/5720))
|
||||
- React DOM does not throw if a `<select>` is unmounted while its `onChange` handler is executing. ([@sambev](https://github.com/sambev) in [#6028](https://github.com/facebook/react/pull/6028))
|
||||
- React DOM does not throw in Windows 8 apps. ([@Andrew8xx8](https://github.com/Andrew8xx8) in [#6063](https://github.com/facebook/react/pull/6063))
|
||||
- React DOM does not throw when asynchronously unmounting a child with a `ref`. ([@yiminghe](https://github.com/yiminghe) in [#6095](https://github.com/facebook/react/pull/6095))
|
||||
- React DOM no longer forces synchronous layout because of scroll position tracking. ([@syranide](https://github.com/syranide) in [#2271](https://github.com/facebook/react/pull/2271))
|
||||
- `Object.is` is used in a number of places to compare values, which leads to fewer false positives, especially involving `NaN`. In particular, this affects the `shallowCompare` add-on. ([@chicoxyzzy](https://github.com/chicoxyzzy) in [#6132](https://github.com/facebook/react/pull/6132))
|
||||
- Add-Ons: ReactPerf no longer instruments adding or removing an event listener because they don’t really touch the DOM due to event delegation. ([@antoaravinth](https://github.com/antoaravinth) in [#5209](https://github.com/facebook/react/pull/5209))
|
||||
|
||||
### Other improvements
|
||||
|
||||
- React now uses `loose-envify` instead of `envify` so it installs fewer transitive dependencies. ([@qerub](https://github.com/qerub) in [#6303](https://github.com/facebook/react/pull/6303))
|
||||
- Shallow renderer now exposes `getMountedInstance()`. ([@glenjamin](https://github.com/glenjamin) in [#4918](https://github.com/facebook/react/pull/4918))
|
||||
- Shallow renderer now returns the rendered output from `render()`. ([@simonewebdesign](https://github.com/simonewebdesign) in [#5411](https://github.com/facebook/react/pull/5411))
|
||||
- React no longer depends on ES5 *shams* for `Object.create` and `Object.freeze` in older environments. It still, however, requires ES5 *shims* in those environments. ([@dgreensp](https://github.com/dgreensp) in [#4959](https://github.com/facebook/react/pull/4959))
|
||||
- React DOM now allows `data-` attributes with names that start with numbers. ([@nLight](https://github.com/nLight) in [#5216](https://github.com/facebook/react/pull/5216))
|
||||
- React DOM adds a new `suppressContentEditableWarning` prop for components like [Draft.js](https://facebook.github.io/draft-js/) that intentionally manage `contentEditable` children with React. ([@mxstbr](https://github.com/mxstbr) in [#6112](https://github.com/facebook/react/pull/6112))
|
||||
- React improves the performance for `createClass()` on complex specs. ([@spicyj](https://github.com/spicyj) in [#5550](https://github.com/facebook/react/pull/5550))
|
||||
|
||||
|
||||
## 0.14.8 (March 29, 2016)
|
||||
|
||||
### React
|
||||
@@ -88,7 +379,7 @@
|
||||
### Major changes
|
||||
|
||||
- Split the main `react` package into two: `react` and `react-dom`. This paves the way to writing components that can be shared between the web version of React and React Native. This means you will need to include both files and some functions have been moved from `React` to `ReactDOM`.
|
||||
- Addons have been moved to seperate packages (`react-addons-clone-with-props`, `react-addons-create-fragment`, `react-addons-css-transition-group`, `react-addons-linked-state-mixin`, `react-addons-perf`, `react-addons-pure-render-mixin`, `react-addons-shallow-compare`, `react-addons-test-utils`, `react-addons-transition-group`, `react-addons-update`, `ReactDOM.unstable_batchedUpdates`).
|
||||
- Addons have been moved to separate packages (`react-addons-clone-with-props`, `react-addons-create-fragment`, `react-addons-css-transition-group`, `react-addons-linked-state-mixin`, `react-addons-perf`, `react-addons-pure-render-mixin`, `react-addons-shallow-compare`, `react-addons-test-utils`, `react-addons-transition-group`, `react-addons-update`, `ReactDOM.unstable_batchedUpdates`).
|
||||
- Stateless functional components - React components were previously created using React.createClass or using ES6 classes. This release adds a [new syntax](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions) where a user defines a single [stateless render function](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions) (with one parameter: `props`) which returns a JSX element, and this function may be used as a component.
|
||||
- Refs to DOM components as the DOM node itself. Previously the only useful thing you can do with a DOM component is call `getDOMNode()` to get the underlying DOM node. Starting with this release, a ref to a DOM component _is_ the actual DOM node. **Note that refs to custom (user-defined) components work exactly as before; only the built-in DOM components are affected by this change.**
|
||||
|
||||
@@ -202,7 +493,7 @@
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* Immutabilty Helpers: Ensure it supports `hasOwnProperty` as an object key
|
||||
* Immutability Helpers: Ensure it supports `hasOwnProperty` as an object key
|
||||
|
||||
### React Tools
|
||||
|
||||
@@ -733,14 +1024,14 @@
|
||||
|
||||
* Upgrade Commoner so `require` statements are no longer relativized when passing through the transformer. This was a feature needed when building React, but doesn't translate well for other consumers of `bin/jsx`.
|
||||
* Upgraded our dependencies on Commoner and Recast so they use a different directory for their cache.
|
||||
* Freeze our esprima dependency.
|
||||
* Freeze our Esprima dependency.
|
||||
|
||||
|
||||
## 0.3.2 (May 31, 2013)
|
||||
|
||||
### JSX
|
||||
|
||||
* Improved compatability with other coding styles (specifically, multiple assignments with a single `var`).
|
||||
* Improved compatibility with other coding styles (specifically, multiple assignments with a single `var`).
|
||||
|
||||
### react-tools
|
||||
|
||||
|
||||
@@ -1,100 +1,5 @@
|
||||
# Contributing to React
|
||||
|
||||
React is one of Facebook's first open source projects that is both under very active development and is also being used to ship code to everybody on [facebook.com](https://www.facebook.com). We're still working out the kinks to make contributing to this project as easy and transparent as possible, but we're not quite there yet. Hopefully this document makes the process for contributing clear and answers some questions that you may have.
|
||||
Want to contribute to React? There are a few things you need to know.
|
||||
|
||||
## [Code of Conduct](https://code.facebook.com/codeofconduct)
|
||||
|
||||
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read [the full text](https://code.facebook.com/codeofconduct) so that you can understand what actions will and will not be tolerated.
|
||||
|
||||
## Our Development Process
|
||||
|
||||
Some of the core team will be working directly on GitHub. These changes will be public from the beginning. Other changesets will come via a bridge with Facebook's internal source control. This is a necessity as it allows engineers at Facebook outside of the core team to move fast and contribute from an environment they are comfortable in.
|
||||
|
||||
### `master` is unsafe
|
||||
|
||||
We will do our best to keep `master` in good shape, with tests passing at all times. But in order to move fast, we will make API changes that your application might not be compatible with. We will do our best to communicate these changes and always version appropriately so you can lock into a specific version if need be.
|
||||
|
||||
### Test Suite
|
||||
|
||||
Use `grunt test` to run the full test suite with PhantomJS.
|
||||
|
||||
This command is just a facade to [Jest](https://facebook.github.io/jest/). You may optionally run `npm install -g jest-cli` and use Jest commands directly to have more control over how tests are executed.
|
||||
|
||||
For example, `jest --watch` lets you automatically run the test suite on every file change.
|
||||
|
||||
You can also run a subset of tests by passing a prefix to `jest`. For instance, `jest ReactDOMSVG` will only run tests in the files that start with `ReactDOMSVG`, such as `ReactDOMSVG-test.js`.
|
||||
|
||||
When you know which tests you want to run, you can achieve a fast feedback loop by using these two features together. For example, `jest ReactDOMSVG --watch` will re-run only the matching tests on every change.
|
||||
|
||||
Just make sure to run the whole test suite before submitting a pull request!
|
||||
|
||||
### Pull Requests
|
||||
|
||||
**Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)
|
||||
|
||||
The core team will be monitoring for pull requests. When we get one, we'll run some Facebook-specific integration tests on it first. From here, we'll need to get another person to sign off on the changes and then merge the pull request. For API changes we may need to fix internal uses, which could cause some delay. We'll do our best to provide updates and feedback throughout the process.
|
||||
|
||||
*Before* submitting a pull request, please make sure the following is done…
|
||||
|
||||
1. Fork the repo and create your branch from `master`.
|
||||
2. If you've added code that should be tested, add tests!
|
||||
3. If you've changed APIs, update the documentation.
|
||||
4. Ensure the test suite passes (`grunt test`).
|
||||
5. Make sure your code lints (`grunt lint`) - we've done our best to make sure these rules match our internal linting guidelines.
|
||||
6. If you haven't already, complete the CLA.
|
||||
|
||||
### Contributor License Agreement (CLA)
|
||||
|
||||
In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Facebook open source project, you're good to go. If you are submitting a pull request for the first time, just let us know that you have completed the CLA and we can cross-check with your GitHub username.
|
||||
|
||||
[Complete your CLA here.](https://code.facebook.com/cla)
|
||||
|
||||
## Bugs
|
||||
|
||||
### Where to Find Known Issues
|
||||
|
||||
We will be using GitHub Issues for our public bugs. We will keep a close eye on this and try to make it clear when we have an internal fix in progress. Before filing a new task, try to make sure your problem doesn't already exist.
|
||||
|
||||
### Reporting New Issues
|
||||
|
||||
The best way to get your bug fixed is to provide a reduced test case. jsFiddle, jsBin, and other sites provide a way to give live examples. Those are especially helpful though may not work for `JSX`-based code.
|
||||
|
||||
### Security Bugs
|
||||
|
||||
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe disclosure of security bugs. With that in mind, please do not file public issues; go through the process outlined on that page.
|
||||
|
||||
## How to Get in Touch
|
||||
|
||||
* IRC - [#reactjs on freenode](https://webchat.freenode.net/?channels=reactjs)
|
||||
* Discussion forum - [discuss.reactjs.org](https://discuss.reactjs.org/)
|
||||
|
||||
## Meeting Notes
|
||||
|
||||
React team meets once a week to discuss the development of React, future plans, and priorities.
|
||||
You can find the meeting notes in a [dedicated repository](https://github.com/reactjs/core-notes/).
|
||||
|
||||
## Style Guide
|
||||
|
||||
Our linter will catch most styling issues that may exist in your code.
|
||||
You can check the status of your code styling by simply running: `grunt lint`
|
||||
|
||||
However, there are still some styles that the linter cannot pick up. If you are unsure about something, looking at [Airbnb's Style Guide](https://github.com/airbnb/javascript) will guide you in the right direction.
|
||||
|
||||
### Code Conventions
|
||||
|
||||
* Use semicolons `;`
|
||||
* Commas last `,`
|
||||
* 2 spaces for indentation (no tabs)
|
||||
* Prefer `'` over `"`
|
||||
* `'use strict';`
|
||||
* 80 character line length
|
||||
* Write "attractive" code
|
||||
* Do not use the optional parameters of `setTimeout` and `setInterval`
|
||||
|
||||
### Documentation
|
||||
|
||||
* Do not wrap lines at 80 characters
|
||||
|
||||
## License
|
||||
|
||||
By contributing to React, you agree that your contributions will be licensed under its BSD license.
|
||||
We wrote a **[contribution guide](https://facebook.github.io/react/contributing/how-to-contribute.html)** to help you get started.
|
||||
|
||||
65
Gruntfile.js
65
Gruntfile.js
@@ -52,10 +52,18 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks(npmTaskName);
|
||||
});
|
||||
|
||||
grunt.registerTask('eslint', require('./grunt/tasks/eslint'));
|
||||
grunt.registerTask('eslint', function() {
|
||||
// Use gulp here.
|
||||
spawnGulp(['eslint'], null, this.async());
|
||||
});
|
||||
|
||||
grunt.registerTask('lint', ['eslint']);
|
||||
|
||||
grunt.registerTask('flow', function() {
|
||||
// Use gulp here.
|
||||
spawnGulp(['flow'], null, this.async());
|
||||
});
|
||||
|
||||
grunt.registerTask('delete-build-modules', function() {
|
||||
// Use gulp here.
|
||||
spawnGulp(['react:clean'], null, this.async());
|
||||
@@ -74,11 +82,22 @@ module.exports = function(grunt) {
|
||||
grunt.registerTask('npm-react-dom:release', npmReactDOMTasks.buildRelease);
|
||||
grunt.registerTask('npm-react-dom:pack', npmReactDOMTasks.packRelease);
|
||||
|
||||
var npmReactNativeTasks = require('./grunt/tasks/npm-react-native');
|
||||
grunt.registerTask('npm-react-native:release', npmReactNativeTasks.buildRelease);
|
||||
grunt.registerTask('npm-react-native:pack', npmReactNativeTasks.packRelease);
|
||||
|
||||
var npmReactAddonsTasks = require('./grunt/tasks/npm-react-addons');
|
||||
grunt.registerTask('npm-react-addons:release', npmReactAddonsTasks.buildReleases);
|
||||
grunt.registerTask('npm-react-addons:pack', npmReactAddonsTasks.packReleases);
|
||||
|
||||
grunt.registerTask('version-check', require('./grunt/tasks/version-check'));
|
||||
var npmReactTestRendererTasks = require('./grunt/tasks/npm-react-test');
|
||||
grunt.registerTask('npm-react-test:release', npmReactTestRendererTasks.buildRelease);
|
||||
grunt.registerTask('npm-react-test:pack', npmReactTestRendererTasks.packRelease);
|
||||
|
||||
grunt.registerTask('version-check', function() {
|
||||
// Use gulp here.
|
||||
spawnGulp(['version-check'], null, this.async());
|
||||
});
|
||||
|
||||
grunt.registerTask('build:basic', [
|
||||
'build-modules',
|
||||
@@ -98,12 +117,41 @@ module.exports = function(grunt) {
|
||||
'build-modules',
|
||||
'browserify:addonsMin',
|
||||
]);
|
||||
grunt.registerTask('build:dom', [
|
||||
'build-modules',
|
||||
'version-check',
|
||||
'browserify:dom',
|
||||
]);
|
||||
grunt.registerTask('build:dom-min', [
|
||||
'build-modules',
|
||||
'version-check',
|
||||
'browserify:domMin',
|
||||
]);
|
||||
grunt.registerTask('build:dom-server', [
|
||||
'build-modules',
|
||||
'version-check',
|
||||
'browserify:domServer',
|
||||
]);
|
||||
grunt.registerTask('build:dom-server-min', [
|
||||
'build-modules',
|
||||
'version-check',
|
||||
'browserify:domServerMin',
|
||||
]);
|
||||
grunt.registerTask('build:dom-fiber', [
|
||||
'build-modules',
|
||||
'version-check',
|
||||
'browserify:domFiber',
|
||||
]);
|
||||
grunt.registerTask('build:dom-fiber-min', [
|
||||
'build-modules',
|
||||
'version-check',
|
||||
'browserify:domFiberMin',
|
||||
]);
|
||||
grunt.registerTask('build:npm-react', [
|
||||
'version-check',
|
||||
'build-modules',
|
||||
'npm-react:release',
|
||||
]);
|
||||
grunt.registerTask('build:react-dom', require('./grunt/tasks/react-dom'));
|
||||
|
||||
var jestTasks = require('./grunt/tasks/jest');
|
||||
grunt.registerTask('jest:normal', jestTasks.normal);
|
||||
@@ -122,13 +170,22 @@ module.exports = function(grunt) {
|
||||
'browserify:addons',
|
||||
'browserify:min',
|
||||
'browserify:addonsMin',
|
||||
'build:react-dom',
|
||||
'browserify:dom',
|
||||
'browserify:domMin',
|
||||
'browserify:domServer',
|
||||
'browserify:domServerMin',
|
||||
'browserify:domFiber',
|
||||
'browserify:domFiberMin',
|
||||
'npm-react:release',
|
||||
'npm-react:pack',
|
||||
'npm-react-dom:release',
|
||||
'npm-react-dom:pack',
|
||||
'npm-react-native:release',
|
||||
'npm-react-native:pack',
|
||||
'npm-react-addons:release',
|
||||
'npm-react-addons:pack',
|
||||
'npm-react-test:release',
|
||||
'npm-react-test:pack',
|
||||
'compare_size',
|
||||
]);
|
||||
|
||||
|
||||
62
README.md
62
README.md
@@ -2,11 +2,9 @@
|
||||
|
||||
React is a JavaScript library for building user interfaces.
|
||||
|
||||
* **Just the UI:** Lots of people use React as the V in MVC. Since React makes no assumptions about the rest of your technology stack, it's easy to try it out on a small feature in an existing project.
|
||||
* **Virtual DOM:** React abstracts away the DOM from you, giving a simpler programming model and better performance. React can also render on the server using Node, and it can power native apps using [React Native](https://facebook.github.io/react-native/).
|
||||
* **Data flow:** React implements one-way reactive data flow which reduces boilerplate and is easier to reason about than traditional data binding.
|
||||
|
||||
**NEW**! Check out our newest project [React Native](https://github.com/facebook/react-native), which uses React and JavaScript to create native mobile apps.
|
||||
* **Declarative:** React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Declarative views make your code more predictable, simpler to understand, and easier to debug.
|
||||
* **Component-Based:** Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM.
|
||||
* **Learn Once, Write Anywhere:** We don't make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code. React can also render on the server using Node and power mobile apps using [React Native](https://facebook.github.io/react-native/).
|
||||
|
||||
[Learn how to use React in your own project](https://facebook.github.io/react/docs/getting-started.html).
|
||||
|
||||
@@ -33,16 +31,16 @@ You'll notice that we used an HTML-like syntax; [we call it JSX](https://faceboo
|
||||
|
||||
## Installation
|
||||
|
||||
The fastest way to get started is to serve JavaScript from the CDN (also available on [cdnjs](https://cdnjs.com/libraries/react) and [jsdelivr](https://www.jsdelivr.com/projects/react)):
|
||||
The fastest way to get started is to serve JavaScript from a CDN. We're using [unpkg](https://unpkg.com/) below but React is also available on [cdnjs](https://cdnjs.com/libraries/react) and [jsdelivr](https://www.jsdelivr.com/projects/react):
|
||||
|
||||
```html
|
||||
<!-- The core React library -->
|
||||
<script src="https://fb.me/react-0.14.8.js"></script>
|
||||
<script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
|
||||
<!-- The ReactDOM Library -->
|
||||
<script src="https://fb.me/react-dom-0.14.8.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
|
||||
```
|
||||
|
||||
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-0.14.8.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
|
||||
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-15.3.2.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
|
||||
|
||||
If you'd like to use [bower](http://bower.io), it's as easy as:
|
||||
|
||||
@@ -56,49 +54,17 @@ And it's just as easy with [npm](http://npmjs.com):
|
||||
npm i --save react
|
||||
```
|
||||
|
||||
## Contribute
|
||||
## Contributing
|
||||
|
||||
The main purpose of this repository is to continue to evolve React core, making it faster and easier to use. If you're interested in helping with that, then keep reading. If you're not interested in helping right now that's ok too. :) Any feedback you have about using React would be greatly appreciated.
|
||||
The main purpose of this repository is to continue to evolve React core, making it faster and easier to use. If you're interested in helping with that, check out our [contribution guide](https://facebook.github.io/react/contributing/how-to-contribute.html).
|
||||
|
||||
### Building Your Copy of React
|
||||
### [Code of Conduct](https://code.facebook.com/codeofconduct)
|
||||
|
||||
The process to build `react.js` is built entirely on top of node.js, using many libraries you may already be familiar with.
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
* You have `node` installed at v4.0.0+ and `npm` at v2.0.0+.
|
||||
* You are familiar with `npm` and know whether or not you need to use `sudo` when installing packages globally.
|
||||
* You are familiar with `git`.
|
||||
|
||||
#### Build
|
||||
|
||||
Once you have the repository cloned, building a copy of `react.js` is really easy.
|
||||
|
||||
```sh
|
||||
# grunt-cli is needed by grunt; you might have this installed already
|
||||
npm install -g grunt-cli
|
||||
npm install
|
||||
grunt build
|
||||
```
|
||||
|
||||
At this point, you should now have a `build/` directory populated with everything you need to use React. The examples should all work.
|
||||
|
||||
### Grunt
|
||||
|
||||
We use grunt to automate many tasks. Run `grunt -h` to see a mostly complete listing. The important ones to know:
|
||||
|
||||
```sh
|
||||
# Build and run tests with PhantomJS
|
||||
grunt test
|
||||
# Lint the code with ESLint
|
||||
grunt lint
|
||||
# Wipe out build directory
|
||||
grunt clean
|
||||
```
|
||||
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read [the full text](https://code.facebook.com/codeofconduct) so that you can understand what actions will and will not be tolerated.
|
||||
|
||||
### Good First Bug
|
||||
To help you get your feet wet and get you familiar with our contribution process, we have a list of [good first bugs](https://github.com/facebook/react/labels/good%20first%20bug) that contain bugs which are fairly easy to fix. This is a great place to get started.
|
||||
|
||||
To help you get your feet wet and get you familiar with our contribution process, we have a list of [good first bugs](https://github.com/facebook/react/labels/good%20first%20bug) that contain bugs which are fairly easy to fix. This is a great place to get started.
|
||||
|
||||
### License
|
||||
|
||||
@@ -108,9 +74,5 @@ React documentation is [Creative Commons licensed](./LICENSE-docs).
|
||||
|
||||
Examples provided in this repository and in the documentation are [separately licensed](./LICENSE-examples).
|
||||
|
||||
### More…
|
||||
|
||||
There's only so much we can cram in here. To read more about the community and guidelines for submitting pull requests, please read the [Contributing document](CONTRIBUTING.md).
|
||||
|
||||
## Troubleshooting
|
||||
See the [Troubleshooting Guide](https://github.com/facebook/react/wiki/Troubleshooting)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
layout: single
|
||||
title: Page Not Found
|
||||
permalink: 404.html
|
||||
---
|
||||
|
||||
We couldn't find what you were looking for.
|
||||
|
||||
16
docs/Gemfile
16
docs/Gemfile
@@ -3,11 +3,12 @@ source 'https://rubygems.org'
|
||||
gem 'rake'
|
||||
|
||||
# jekyll, which builds it all
|
||||
# 2.0 includes sass processing
|
||||
gem 'jekyll', '~>2.0'
|
||||
# 3.0 includes sass processing
|
||||
gem 'jekyll', '~>3.1'
|
||||
|
||||
# Auto redirect pages
|
||||
# Jekyll extensions
|
||||
gem 'jekyll-redirect-from'
|
||||
gem 'jekyll-paginate'
|
||||
|
||||
# JSON
|
||||
gem 'json'
|
||||
@@ -17,3 +18,12 @@ gem 'rb-fsevent'
|
||||
|
||||
# For markdown header cleanup
|
||||
gem 'sanitize', '~>2.0'
|
||||
|
||||
# Markdown
|
||||
gem 'redcarpet'
|
||||
|
||||
# Syntax highlighting
|
||||
gem 'pygments.rb'
|
||||
|
||||
# Avoid having to poll for changes on Windows
|
||||
gem 'wdm', '>= 0.1.0' if Gem.win_platform?
|
||||
@@ -1,85 +1,70 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
blankslate (2.1.2.4)
|
||||
celluloid (0.15.2)
|
||||
timers (~> 1.1.0)
|
||||
classifier (1.3.4)
|
||||
fast-stemmer (>= 1.0.0)
|
||||
coffee-script (2.3.0)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.7.1)
|
||||
colorator (0.1)
|
||||
execjs (2.2.1)
|
||||
fast-stemmer (1.0.2)
|
||||
ffi (1.9.3)
|
||||
jekyll (2.2.0)
|
||||
classifier (~> 1.3)
|
||||
ffi (1.9.14)
|
||||
ffi (1.9.14-x64-mingw32)
|
||||
jekyll (3.1.6)
|
||||
colorator (~> 0.1)
|
||||
jekyll-coffeescript (~> 1.0)
|
||||
jekyll-gist (~> 1.0)
|
||||
jekyll-paginate (~> 1.0)
|
||||
jekyll-sass-converter (~> 1.0)
|
||||
jekyll-watch (~> 1.0)
|
||||
jekyll-watch (~> 1.1)
|
||||
kramdown (~> 1.3)
|
||||
liquid (~> 2.6.1)
|
||||
liquid (~> 3.0)
|
||||
mercenary (~> 0.3.3)
|
||||
pygments.rb (~> 0.6.0)
|
||||
redcarpet (~> 3.1)
|
||||
rouge (~> 1.7)
|
||||
safe_yaml (~> 1.0)
|
||||
toml (~> 0.1.0)
|
||||
jekyll-coffeescript (1.0.0)
|
||||
coffee-script (~> 2.2)
|
||||
jekyll-gist (1.1.0)
|
||||
jekyll-paginate (1.0.0)
|
||||
jekyll-redirect-from (0.5.0)
|
||||
jekyll (~> 2.0)
|
||||
jekyll-sass-converter (1.2.0)
|
||||
sass (~> 3.2)
|
||||
jekyll-watch (1.1.0)
|
||||
listen (~> 2.7)
|
||||
json (1.8.1)
|
||||
kramdown (1.4.1)
|
||||
liquid (2.6.1)
|
||||
listen (2.7.9)
|
||||
celluloid (>= 0.15.2)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
rb-inotify (>= 0.9)
|
||||
mercenary (0.3.4)
|
||||
mini_portile (0.6.0)
|
||||
nokogiri (1.6.3.1)
|
||||
mini_portile (= 0.6.0)
|
||||
parslet (1.5.0)
|
||||
blankslate (~> 2.0)
|
||||
posix-spawn (0.3.9)
|
||||
pygments.rb (0.6.0)
|
||||
jekyll-paginate (1.1.0)
|
||||
jekyll-redirect-from (0.11.0)
|
||||
jekyll (>= 2.0)
|
||||
jekyll-sass-converter (1.4.0)
|
||||
sass (~> 3.4)
|
||||
jekyll-watch (1.4.0)
|
||||
listen (~> 3.0, < 3.1)
|
||||
json (2.0.1)
|
||||
kramdown (1.11.1)
|
||||
liquid (3.0.6)
|
||||
listen (3.0.8)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
mercenary (0.3.6)
|
||||
mini_portile2 (2.1.0)
|
||||
nokogiri (1.6.8)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
pkg-config (~> 1.1.7)
|
||||
nokogiri (1.6.8-x64-mingw32)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
pkg-config (~> 1.1.7)
|
||||
pkg-config (1.1.7)
|
||||
posix-spawn (0.3.11)
|
||||
pygments.rb (0.6.3)
|
||||
posix-spawn (~> 0.3.6)
|
||||
yajl-ruby (~> 1.1.0)
|
||||
rake (10.3.2)
|
||||
rb-fsevent (0.9.4)
|
||||
rb-inotify (0.9.5)
|
||||
yajl-ruby (~> 1.2.0)
|
||||
rake (11.2.2)
|
||||
rb-fsevent (0.9.7)
|
||||
rb-inotify (0.9.7)
|
||||
ffi (>= 0.5.0)
|
||||
redcarpet (3.1.2)
|
||||
redcarpet (3.3.4)
|
||||
rouge (1.11.1)
|
||||
safe_yaml (1.0.4)
|
||||
sanitize (2.0.6)
|
||||
sanitize (2.1.0)
|
||||
nokogiri (>= 1.4.4)
|
||||
sass (3.3.14)
|
||||
timers (1.1.0)
|
||||
toml (0.1.1)
|
||||
parslet (~> 1.5.0)
|
||||
yajl-ruby (1.1.0)
|
||||
sass (3.4.22)
|
||||
yajl-ruby (1.2.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x64-mingw32
|
||||
|
||||
DEPENDENCIES
|
||||
jekyll (~> 2.0)
|
||||
jekyll (~> 3.1)
|
||||
jekyll-paginate
|
||||
jekyll-redirect-from
|
||||
json
|
||||
pygments.rb
|
||||
rake
|
||||
rb-fsevent
|
||||
redcarpet
|
||||
sanitize (~> 2.0)
|
||||
|
||||
BUNDLED WITH
|
||||
1.10.1
|
||||
1.11.2
|
||||
|
||||
@@ -61,8 +61,15 @@ task :update_acknowledgements do
|
||||
File.open('_data/acknowledgements.yml', 'w+') { |f| f.write(cols.to_yaml) }
|
||||
end
|
||||
|
||||
desc "copy error codes to docs"
|
||||
task :copy_error_codes do
|
||||
codes_json = File.read('../scripts/error-codes/codes.json')
|
||||
codes_js = "var errorMap = #{codes_json.chomp};\n"
|
||||
File.write('js/errorMap.js', codes_js)
|
||||
end
|
||||
|
||||
desc "build into ../../react-gh-pages"
|
||||
task :release => [:update_version, :js, :fetch_remotes] do
|
||||
task :release => [:update_version, :js, :fetch_remotes, :copy_error_codes] do
|
||||
system "jekyll build -d ../../react-gh-pages"
|
||||
end
|
||||
|
||||
|
||||
@@ -5,21 +5,37 @@ url: https://facebook.github.io
|
||||
baseurl: "/react"
|
||||
permalink: "/blog/:year/:month/:day/:title.html"
|
||||
paginate_path: "/blog/page:num/"
|
||||
relative_permalinks: true
|
||||
paginate: 5
|
||||
timezone: America/Los_Angeles
|
||||
highlighter: pygments
|
||||
defaults:
|
||||
- scope:
|
||||
path: ''
|
||||
type: post
|
||||
type: posts
|
||||
values:
|
||||
layout: post
|
||||
sectionid: blog
|
||||
- scope:
|
||||
path: blog
|
||||
type: pages
|
||||
values:
|
||||
sectionid: blog
|
||||
- scope:
|
||||
path: docs
|
||||
type: page
|
||||
type: pages
|
||||
values:
|
||||
layout: docs
|
||||
sectionid: docs
|
||||
- scope:
|
||||
path: tips
|
||||
type: pages
|
||||
values:
|
||||
sectionid: docs
|
||||
- scope:
|
||||
path: contributing
|
||||
type: pages
|
||||
values:
|
||||
sectionid: docs
|
||||
exclude:
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
@@ -36,13 +52,14 @@ sass:
|
||||
sass_dir: _css
|
||||
gems:
|
||||
- jekyll-redirect-from
|
||||
react_version: 0.14.7
|
||||
- jekyll-paginate
|
||||
react_version: 15.3.2
|
||||
react_hashes:
|
||||
dev: xQae1pUPdAKUe0u0KUTNt09zzdwheX4VSUsV8vatqM+t6X7rta01qOzessL808ox
|
||||
prod: zTm/dblzLXQNp3CgY+hfaC/WJ6h4XtNrePh2CW2+rO9GPuNiPb9jmthvAL+oI/dQ
|
||||
addons_dev: I5TF2q2QDmB31aN5lcClArdUo+WJH/Yi3hcH3PBVXFe5DYtYCFh7Jx/dmpba12zn
|
||||
addons_prod: KPHTQfiYMhtsIRbZcY4ri1lBYZQbj4ePsSdzODR2Bu5L5ts3APVyqwKPBThO5Hgc
|
||||
dom_dev: A1t0GCrR06cTHvMjaxeSE8XOiz6j7NvWdmxhN/9z748wEvJTVk13Rr8gMzTUnd8G
|
||||
dom_prod: ntqCsHbLdMxT352UbhPbT7fqjE8xi4jLmQYQa8mYR+ylAapbXRfdsDweueDObf7m
|
||||
dom_server_dev: 3I5+eGB/ILYa6pQQX+rM9O0SyDltamM40RiZ5JvIijSYEfVGZU0vY4Iwx9a1eYyD
|
||||
dom_server_prod: Kt9dEqXzv00orFPW2o3H+kxQtSiNO8EqXsXJT3i99rCcp74N/Km98V0kUxAzy44k
|
||||
dev: bQIyvl+8Ufi5KiKZPG9VItNWmhcAXA1pa5nHIEoBGob+rdbjJnpNV3s288Mz2yZu
|
||||
prod: drG4TSBgFQ0Hb/A3ynRyFDT22irpJDL+duuxvYD5mkC9adCYDqEwnX13371waqiH
|
||||
addons_dev: gCLxBq3yes/qREmjcw3Tdk5dUh3iB54huWqgxq1lAJZTYzLahJqEik5ZiVnq9Zt4
|
||||
addons_prod: pmUKSclxJREtkrfcUJvBYTEoJCvO6Vj5ob8IgPSiIX0G3c4w2dKBJMoGEhlv9Gev
|
||||
dom_dev: ZzFfcTbsRst34N23lWs6TtlfonXwDgpeALh+ObwYXav5BSo0j7KsaAtcdn+xrnS1
|
||||
dom_prod: MTxlP+/p3lyvc2+LZc2B5xy5reGwrA80whnflxNc6zPgLUmMvbwUoKy7qorBH+P4
|
||||
dom_server_dev: jHjmbawtj2AhVuJlmE/O1HXAIbQMzHvoXRZEVdhTSrfJXACRVpZm/BpuAi4K89xn
|
||||
dom_server_prod: LCYUMPll/9t/UsNa/Q1zfti2awxxiiczBUZcQBdeGACH0sU6BEAllZuGxo5b6/kf
|
||||
|
||||
@@ -37,7 +37,7 @@ html * {
|
||||
border-bottom: 1px dotted #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-keyword {
|
||||
color: #268bd2;
|
||||
color: #859900;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-atom {
|
||||
color: #2aa198;
|
||||
@@ -61,7 +61,7 @@ html * {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-property {
|
||||
color: #637c84;
|
||||
color: #657b83;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-operator {
|
||||
color: #657b83;
|
||||
@@ -74,14 +74,13 @@ html * {
|
||||
border-bottom: 1px dotted #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-bracket {
|
||||
color: #cb4b16;
|
||||
color: #268bd2;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-tag {
|
||||
color: #657b83;
|
||||
color: #268bd2;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-attribute {
|
||||
color: #586e75;
|
||||
font-weight: bold;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-meta {
|
||||
color: #268bd2;
|
||||
@@ -166,7 +165,6 @@ html * {
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-attribute {
|
||||
color: #93a1a1;
|
||||
font-weight: bold;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-meta {
|
||||
color: #268bd2;
|
||||
|
||||
@@ -112,8 +112,6 @@ li {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
a {
|
||||
color: $linkColor;
|
||||
text-decoration: none;
|
||||
@@ -131,3 +129,7 @@ a {
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
input {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
@@ -2,17 +2,21 @@
|
||||
- - '839'
|
||||
- Aaron Franks
|
||||
- Aaron Gelter
|
||||
- Adam Bloomston
|
||||
- Adam Krebs
|
||||
- Adam Mark
|
||||
- Adam Solove
|
||||
- Adam Timberlake
|
||||
- Adam Zapletal
|
||||
- Ahmad Wali Sidiqi
|
||||
- Alan Plum
|
||||
- Alan Souza
|
||||
- Alan deLevie
|
||||
- Alastair Hole
|
||||
- Alex
|
||||
- Alex Boatwright
|
||||
- Alex Boyd
|
||||
- Alex Dajani
|
||||
- Alex Lopatin
|
||||
- Alex Mykyta
|
||||
- Alex Pien
|
||||
@@ -24,22 +28,28 @@
|
||||
- Alexandre Gaudencio
|
||||
- Alexey Raspopov
|
||||
- Alexey Shamrin
|
||||
- Ali Ukani
|
||||
- Andre Z Sanchez
|
||||
- Andreas Savvides
|
||||
- Andreas Svensson
|
||||
- Andres Kalle
|
||||
- Andres Suarez
|
||||
- Andrew Clark
|
||||
- Andrew Cobby
|
||||
- Andrew Davey
|
||||
- Andrew Henderson
|
||||
- Andrew Kulakov
|
||||
- Andrew Rasmussen
|
||||
- Andrew Sokolov
|
||||
- Andrew Zich
|
||||
- Andrey Popp
|
||||
- Anthony van der Hoorn
|
||||
- Anto Aravinth
|
||||
- Antonio Ruberto
|
||||
- Antti Ahti
|
||||
- Anuj Tomar
|
||||
- AoDev
|
||||
- April Arcus
|
||||
- Areeb Malik
|
||||
- Aria Buckles
|
||||
- Aria Stewart
|
||||
@@ -54,7 +64,9 @@
|
||||
- Beau Smith
|
||||
- Ben Alpert
|
||||
- Ben Anderson
|
||||
- Ben Brooks
|
||||
- Ben Foxall
|
||||
- Ben Halpern
|
||||
- Ben Jaffe
|
||||
- Ben Moss
|
||||
- Ben Newman
|
||||
@@ -62,16 +74,20 @@
|
||||
- Benjamin Keen
|
||||
- Benjamin Leiken
|
||||
- Benjamin Woodruff
|
||||
- Benjy Cui
|
||||
- Bill Blanchard
|
||||
- Bill Fisher
|
||||
- Blaine Hatab
|
||||
- Blaine Kasten
|
||||
- Bob Eagan
|
||||
- Bob Ralian
|
||||
- Bob Renwick
|
||||
- Bobby
|
||||
- Bojan Mihelac
|
||||
- Bradley Spaulding
|
||||
- Brandon Bloom
|
||||
- Brandon Tilley
|
||||
- Brenard Cubacub
|
||||
- Brian Cooke
|
||||
- Brian Holt
|
||||
- Brian Hsu
|
||||
@@ -82,14 +98,19 @@
|
||||
- Bruno Škvorc
|
||||
- Cam Song
|
||||
- Cam Spiers
|
||||
- Cameron Chamberlain
|
||||
- Cameron Matheson
|
||||
- Carter Chung
|
||||
- Cassus Adam Banko
|
||||
- Cat Chen
|
||||
- Cedric Sohrauer
|
||||
- Cesar William Alvarenga
|
||||
- Changsoon Bok
|
||||
- Charles Marsh
|
||||
- Chase Adams
|
||||
- Cheng Lou
|
||||
- Chitharanjan Das
|
||||
- Chris Bolin
|
||||
- Chris Grovers
|
||||
- Chris Ha
|
||||
- Chris Rebert
|
||||
@@ -97,12 +118,15 @@
|
||||
- Christian Alfoni
|
||||
- Christian Oliff
|
||||
- Christian Roman
|
||||
- Christoffer Sawicki
|
||||
- Christoph Pojer
|
||||
- Christopher Monsanto
|
||||
- Clay Allsopp
|
||||
- Connor McSheffrey
|
||||
- Conor Hastings
|
||||
- Cory House
|
||||
- Cotton Hou
|
||||
- Craig Akimoto
|
||||
- Cristovao Verstraeten
|
||||
- Damien Pellier
|
||||
- Dan Abramov
|
||||
@@ -113,6 +137,7 @@
|
||||
- Daniel Friesen
|
||||
- Daniel Gasienica
|
||||
- Daniel Hejl
|
||||
- Daniel Hejl
|
||||
- Daniel Lo Nigro
|
||||
- Daniel Mané
|
||||
- Daniel Miladinov
|
||||
@@ -122,23 +147,31 @@
|
||||
- Darcy
|
||||
- Daryl Lau
|
||||
- Darío Javier Cravero
|
||||
- Dave Galbraith
|
||||
- David Baker
|
||||
- David Ed Mellum
|
||||
- David Goldberg
|
||||
- David Granado
|
||||
- David Greenspan
|
||||
- David Hellsing
|
||||
- David Hu
|
||||
- David Khourshid
|
||||
- David Mininger
|
||||
- David Neubauer
|
||||
- David Percy
|
||||
- Dean Shi
|
||||
- Denis Sokolov
|
||||
- Deniss Jacenko
|
||||
- Dennis Johnson
|
||||
- Devon Blandin
|
||||
- Devon Harvey
|
||||
- Dmitrii Abramov
|
||||
- Dmitriy Rozhkov
|
||||
- Dmitry Blues
|
||||
- Dmitry Mazuro
|
||||
- Domenico Matteo
|
||||
- Don Abrams
|
||||
- Dongsheng Liu
|
||||
- Dustan Kasten
|
||||
- Dustin Getz
|
||||
- Dylan Harrington
|
||||
@@ -154,6 +187,7 @@
|
||||
- Erik Harper
|
||||
- Espen Hovlandsdal
|
||||
- Evan Coonrod
|
||||
- Evan Vosberg
|
||||
- Fabio M. Costa
|
||||
- Federico Rampazzo
|
||||
- Felipe Oliveira Carvalho
|
||||
@@ -163,11 +197,15 @@
|
||||
- Frankie Bagnardi
|
||||
- François-Xavier Bois
|
||||
- Fred Zhao
|
||||
- Freddy Rangel
|
||||
- Fyodor Ivanishchev
|
||||
- G Scott Olson
|
||||
- G. Kay Lee
|
||||
- Gabe Levi
|
||||
- Gajus Kuizinas
|
||||
- Gareth Nicholson
|
||||
- Garren Smith
|
||||
- Gavin McQuistin
|
||||
- Geert Pasteels
|
||||
- Geert-Jan Brits
|
||||
- George A Sisco III
|
||||
@@ -183,44 +221,57 @@
|
||||
- Guido Bouman
|
||||
- Harry Hull
|
||||
- Harry Marr
|
||||
- - Harry Moreno
|
||||
- Harry Moreno
|
||||
- Harshad Sabne
|
||||
- Hekar Khani
|
||||
- Hendrik Swanepoel
|
||||
- Henrik Nyh
|
||||
- Henry Wong
|
||||
- Henry Zhu
|
||||
- Hideo Matsumoto
|
||||
- Hou Chia
|
||||
- Huang-Wei Chang
|
||||
- - Hugo Agbonon
|
||||
- Hugo Jobling
|
||||
- Hyeock Kwon
|
||||
- Héliton Nordt
|
||||
- Ian Obermiller
|
||||
- Ignacio Carbajo
|
||||
- Igor Scekic
|
||||
- Ilia Pavlenkov
|
||||
- Ilya Shuklin
|
||||
- Ilyá Belsky
|
||||
- Ingvar Stepanyan
|
||||
- Irae Carvalho
|
||||
- Isaac Salier-Hellendag
|
||||
- Iurii Kucherov
|
||||
- Ivan Kozik
|
||||
- Ivan Krechetov
|
||||
- Ivan Vergiliev
|
||||
- J. Andrew Brassington
|
||||
- J. Renée Beach
|
||||
- JD Isaacks
|
||||
- JJ Weber
|
||||
- JW
|
||||
- Jack Zhang
|
||||
- Jackie Wung
|
||||
- Jacob Gable
|
||||
- Jacob Greenleaf
|
||||
- Jae Hun Ro
|
||||
- Jaeho Lee
|
||||
- Jaime Mingo
|
||||
- Jake Worth
|
||||
- Jakub Malinowski
|
||||
- James
|
||||
- James Brantly
|
||||
- James Burnett
|
||||
- James Friend
|
||||
- James Ide
|
||||
- James Long
|
||||
- James Pearce
|
||||
- James Seppi
|
||||
- James South
|
||||
- James Wen
|
||||
- Jamie Wong
|
||||
- Jamis Charles
|
||||
- Jamison Dance
|
||||
@@ -246,6 +297,7 @@
|
||||
- Jeff Morrison
|
||||
- Jeff Welch
|
||||
- Jeffrey Lin
|
||||
- Jeremy Fairbank
|
||||
- Jesse Skinner
|
||||
- Jignesh Kakadiya
|
||||
- Jim OBrien
|
||||
@@ -253,14 +305,19 @@
|
||||
- Jimmy Jea
|
||||
- Jing Chen
|
||||
- Jinwoo Oh
|
||||
- Jinxiu Lee
|
||||
- Jiyeon Seo
|
||||
- Jody McIntyre
|
||||
- Joe Critchley
|
||||
- Joe Stein
|
||||
- Joel Auterson
|
||||
- Johannes Baiter
|
||||
- Johannes Emerich
|
||||
- Johannes Lumpe
|
||||
- John Heroy
|
||||
- John Ryan
|
||||
- John Watson
|
||||
- John-David Dalton
|
||||
- Jon Beebe
|
||||
- Jon Chester
|
||||
- Jon Hester
|
||||
@@ -270,6 +327,7 @@
|
||||
- Jonas Enlund
|
||||
- Jonas Gebhardt
|
||||
- Jonathan Hsu
|
||||
- Jonathan Persson
|
||||
- Jordan Harband
|
||||
- Jordan Walke
|
||||
- Jorrit Schippers
|
||||
@@ -277,7 +335,9 @@
|
||||
- Joseph Savona
|
||||
- Josh Bassett
|
||||
- Josh Duck
|
||||
- Josh Perez
|
||||
- Josh Yudaken
|
||||
- Joshua Evans
|
||||
- Joshua Go
|
||||
- Joshua Goldberg
|
||||
- Joshua Ma
|
||||
@@ -286,23 +346,34 @@
|
||||
- Julen Ruiz Aizpuru
|
||||
- Julian Viereck
|
||||
- Julien Bordellier
|
||||
- Julio Lopez
|
||||
- Jun Wu
|
||||
- Juraj Dudak
|
||||
- Justas Brazauskas
|
||||
- Justin Jaffray
|
||||
- Justin Robison
|
||||
- Justin Woo
|
||||
- Kale
|
||||
- Kamron Batman
|
||||
- Karl Mikkelsen
|
||||
- Karpich Dmitry
|
||||
- Keito Uchiyama
|
||||
- Ken Powers
|
||||
- Kent C. Dodds
|
||||
- Kevin Cheng
|
||||
- Kevin Coughlin
|
||||
- Kevin Huang
|
||||
- Kevin Lau
|
||||
- Kevin Old
|
||||
- Kevin Robinson
|
||||
- Kewei Jiang
|
||||
- Kier Borromeo
|
||||
- KimCoding
|
||||
- Kirk Steven Hansen
|
||||
- Kit Randel
|
||||
- Kohei TAKATA
|
||||
- Koo Youngmin
|
||||
- Krystian Karczewski
|
||||
- Kunal Mehta
|
||||
- Kurt Ruppel
|
||||
- Kyle Kelley
|
||||
@@ -312,6 +383,7 @@
|
||||
- Lee Byron
|
||||
- Lee Jaeyoung
|
||||
- Lei
|
||||
- Leland Richardson
|
||||
- Leon Fedotov
|
||||
- Leon Yip
|
||||
- Leonardo YongUk Kim
|
||||
@@ -319,9 +391,13 @@
|
||||
- Levi McCallum
|
||||
- Lily
|
||||
- Logan Allen
|
||||
- Lovisa Svallingson
|
||||
- Ludovico Fischer
|
||||
- Luigy Leon
|
||||
- Luke Horvat
|
||||
- MIKAMI Yoshiyuki
|
||||
- Maher Beg
|
||||
- Manas
|
||||
- Marcin K.
|
||||
- Marcin Kwiatkowski
|
||||
- Marcin Szczepanski
|
||||
@@ -331,59 +407,83 @@
|
||||
- Mark Funk
|
||||
- Mark Hintz
|
||||
- Mark IJbema
|
||||
- Mark Murphy
|
||||
- Mark Richardson
|
||||
- Mark Rushakoff
|
||||
- Mark Sun
|
||||
- Marlon Landaverde
|
||||
- Marshall Roch
|
||||
- Martin Andert
|
||||
- Martin Hujer
|
||||
- Martin Jul
|
||||
- Martin Konicek
|
||||
- Martin Mihaylov
|
||||
- Masaki KOBAYASHI
|
||||
- Mathieu M-Gosselin
|
||||
- Mathieu Savy
|
||||
- Matias Singers
|
||||
- Matsunoki
|
||||
- Matt Brookes
|
||||
- Matt Dunn-Rankin
|
||||
- Matt Harrison
|
||||
- Matt Huggins
|
||||
- Matt Stow
|
||||
- Matt Zabriskie
|
||||
- Matthew Dapena-Tretter
|
||||
- Matthew Herbst
|
||||
- Matthew Hodgson
|
||||
- Matthew Johnston
|
||||
- Matthew King
|
||||
- Matthew Looi
|
||||
- Matthew Miner
|
||||
- Matthias Le Brun
|
||||
- Matti Nelimarkka
|
||||
- Mattijs Kneppers
|
||||
- Max F. Albrecht
|
||||
- Max Heiber
|
||||
- Max Stoiber
|
||||
- Maxi Ferreira
|
||||
- Maxim Abramchuk
|
||||
- Merrick Christensen
|
||||
- Mert Kahyaoğlu
|
||||
- Michael Chan
|
||||
- Michael McDermott
|
||||
- Michael Randers-Pehrson
|
||||
- Michael Ridgway
|
||||
- Michael Warner
|
||||
- Michael Wiencek
|
||||
- Michael Ziwisky
|
||||
- Michal Srb
|
||||
- Michelle Todd
|
||||
- Mihai Parparita
|
||||
- Mike D Pilsbury
|
||||
- - Mike Groseclose
|
||||
- Mike Groseclose
|
||||
- Mike Nordick
|
||||
- Mikolaj Dadela
|
||||
- Miles Johnson
|
||||
- Minwe LUO
|
||||
- Miorel Palii
|
||||
- Morhaus
|
||||
- - Morhaus
|
||||
- Moshe Kolodny
|
||||
- Mouad Debbar
|
||||
- Murad
|
||||
- Murray M. Moss
|
||||
- Nadeesha Cabral
|
||||
- Naman Goel
|
||||
- Nate Hunzaker
|
||||
- Nate Lee
|
||||
- Nathan Smith
|
||||
- Nathan White
|
||||
- Nee
|
||||
- Neri Marschik
|
||||
- Nguyen Truong Duy
|
||||
- Nicholas Bergson-Shilcock
|
||||
- Nicholas Clawson
|
||||
- Nick Balestra
|
||||
- Nick Fitzgerald
|
||||
- Nick Gavalas
|
||||
- Nick Merwin
|
||||
- Nick Presta
|
||||
- Nick Raienko
|
||||
- Nick Thompson
|
||||
- Nick Williams
|
||||
@@ -399,8 +499,10 @@
|
||||
- Pablo Lacerda de Miranda
|
||||
- Paolo Moretti
|
||||
- Pascal Hartig
|
||||
- Patrick
|
||||
- Patrick Laughlin
|
||||
- Patrick Stapleton
|
||||
- Paul Benigeri
|
||||
- Paul Harper
|
||||
- Paul O’Shannessy
|
||||
- Paul Seiffert
|
||||
@@ -410,19 +512,25 @@
|
||||
- Peter Blazejewicz
|
||||
- Peter Cottle
|
||||
- Peter Jaros
|
||||
- Peter Newnham
|
||||
- Petri Lehtinen
|
||||
- Petri Lievonen
|
||||
- Pieter Vanderwerff
|
||||
- Pouja Nikray
|
||||
- Prathamesh Sonpatki
|
||||
- Prayag Verma
|
||||
- Preston Parry
|
||||
- Rafael
|
||||
- Rafal Dittwald
|
||||
- Rainer Oviir
|
||||
- Rajat Sehgal
|
||||
- Rajiv Tirumalareddy
|
||||
- Ram Kaniyur
|
||||
- Randall Randall
|
||||
- Ray
|
||||
- Raymond Ha
|
||||
- Reed Loden
|
||||
- Remko Tronçon
|
||||
- Richard D. Worth
|
||||
- Richard Feldman
|
||||
- Richard Kho
|
||||
@@ -430,16 +538,22 @@
|
||||
- Richard Livesey
|
||||
- Richard Wood
|
||||
- Rick Beerendonk
|
||||
- Rick Ford
|
||||
- Riley Tomasek
|
||||
- Rob Arnold
|
||||
- Robert Binna
|
||||
- Robert Knight
|
||||
- Robert Sedovsek
|
||||
- Robin Berjon
|
||||
- Robin Frischmann
|
||||
- Roman Pominov
|
||||
- Roman Vanesyan
|
||||
- Russ
|
||||
- Ryan Seddon
|
||||
- Sahat Yalkabov
|
||||
- Saif Hakim
|
||||
- Saiichi Hashimoto
|
||||
- Sam Beveridge
|
||||
- Sam Saccone
|
||||
- Sam Selikoff
|
||||
- Samy Al Zahrani
|
||||
@@ -448,7 +562,9 @@
|
||||
- Scott Feeney
|
||||
- Sean Kinsey
|
||||
- Sebastian Markbåge
|
||||
- Sebastian McKenzie
|
||||
- Seoh Char
|
||||
- Sercan Eraslan
|
||||
- Serg
|
||||
- Sergey Generalov
|
||||
- Sergey Rubanov
|
||||
@@ -457,18 +573,25 @@
|
||||
- Shaun Trennery
|
||||
- ShihChi Huang
|
||||
- Shim Won
|
||||
- Shinnosuke Watanabe
|
||||
- Shogun Sea
|
||||
- Shota Kubota
|
||||
- Shripad K
|
||||
- Sibi
|
||||
- Simen Bekkhus
|
||||
- Simon Højberg
|
||||
- Simon Welsh
|
||||
- Simone Vittori
|
||||
- Soichiro Kawamura
|
||||
- Sophia Westwood
|
||||
- Sota Ohara
|
||||
- Spencer Handley
|
||||
- Stefan Dombrowski
|
||||
- Stephen Murphy
|
||||
- Sterling Cobb
|
||||
- Steve Baker
|
||||
- Steven Luscher
|
||||
- Steven Vachon
|
||||
- Stoyan Stefanov
|
||||
- Sundeep Malladi
|
||||
- Sunny Juneja
|
||||
@@ -479,9 +602,11 @@
|
||||
- Taeho Kim
|
||||
- Tay Yang Shun
|
||||
- Ted Kim
|
||||
- Tengfei Guo
|
||||
- Teodor Szente
|
||||
- Thomas Aylott
|
||||
- Thomas Boyt
|
||||
- Thomas Broadley
|
||||
- Thomas Reggi
|
||||
- Thomas Röggla
|
||||
- Thomas Shaddox
|
||||
@@ -491,12 +616,15 @@
|
||||
- Tim Routowicz
|
||||
- Tim Schaub
|
||||
- Timothy Yung
|
||||
- Timur Carpeev
|
||||
- Tobias Reiss
|
||||
- Tom Duncalf
|
||||
- Tom Haggie
|
||||
- Tom Hauburger
|
||||
- Tom MacWright
|
||||
- Tom Occhino
|
||||
- Tomasz Kołodziejski
|
||||
- Tomoya Suzuki
|
||||
- Tony Spiro
|
||||
- Toru Kobayashi
|
||||
- Trinh Hoang Nhu
|
||||
@@ -507,14 +635,17 @@
|
||||
- Varun Rau
|
||||
- Vasiliy Loginevskiy
|
||||
- Victor Alvarez
|
||||
- Victor Homyakov
|
||||
- Victor Koenders
|
||||
- Ville Immonen
|
||||
- Vincent Riemer
|
||||
- Vincent Siao
|
||||
- Vipul A M
|
||||
- Vitaly Kramskikh
|
||||
- Vitor Balocco
|
||||
- Vjeux
|
||||
- Volkan Unsal
|
||||
- Wander Wang
|
||||
- Wayne Larsen
|
||||
- WickyNilliams
|
||||
- Wincent Colaiuta
|
||||
@@ -526,9 +657,14 @@
|
||||
- YouBao Nong
|
||||
- Yuichi Hagio
|
||||
- Yuriy Dybskiy
|
||||
- Yutaka Nakajima
|
||||
- Yuval Dekel
|
||||
- Zach Bruggeman
|
||||
- Zach Ramaekers
|
||||
- Zacharias
|
||||
- Zeke Sikelianos
|
||||
- Zhangjd
|
||||
- adraeth
|
||||
- arush
|
||||
- brafdlog
|
||||
- chen
|
||||
@@ -539,14 +675,23 @@
|
||||
- dongmeng.ldm
|
||||
- iamchenxin
|
||||
- iamdoron
|
||||
- iawia002
|
||||
- imagentleman
|
||||
- koh-taka
|
||||
- kohashi85
|
||||
- laiso
|
||||
- leeyoungalias
|
||||
- li.li
|
||||
- maxprafferty
|
||||
- rgarifullin
|
||||
- songawee
|
||||
- sugarshin
|
||||
- wali-s
|
||||
- yiminghe
|
||||
- youmoo
|
||||
- zhangjg
|
||||
- Árni Hermann Reynisson
|
||||
- 凌恒
|
||||
- 张敏
|
||||
- zwhitchcox
|
||||
- "Árni Hermann Reynisson"
|
||||
- "元彦"
|
||||
- "凌恒"
|
||||
- "张敏"
|
||||
|
||||
@@ -31,6 +31,9 @@ jingc:
|
||||
josephsavona:
|
||||
name: Joseph Savona
|
||||
url: https://twitter.com/en_JS
|
||||
keyanzhang:
|
||||
name: Keyan Zhang
|
||||
url: https://twitter.com/keyanzhang
|
||||
kmeht:
|
||||
name: Kunal Mehta
|
||||
url: https://github.com/kmeht
|
||||
|
||||
8
docs/_data/nav_contributing.yml
Normal file
8
docs/_data/nav_contributing.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
- title: Contributing
|
||||
items:
|
||||
- id: how-to-contribute
|
||||
title: How to Contribute
|
||||
- id: codebase-overview
|
||||
title: Codebase Overview
|
||||
- id: design-principles
|
||||
title: Design Principles
|
||||
@@ -48,6 +48,13 @@
|
||||
title: Refs to Components
|
||||
- id: tooling-integration
|
||||
title: Tooling Integration
|
||||
subitems:
|
||||
- id: language-tooling
|
||||
title: Language Tooling
|
||||
- id: package-management
|
||||
title: Package Management
|
||||
- id: environments
|
||||
title: Server-side Environments
|
||||
- id: addons
|
||||
title: Add-Ons
|
||||
subitems:
|
||||
@@ -95,11 +102,3 @@
|
||||
title: Web Components
|
||||
- id: glossary
|
||||
title: React (Virtual) DOM Terminology
|
||||
- title: Flux
|
||||
items:
|
||||
- id: flux-overview
|
||||
title: Flux Overview
|
||||
href: https://facebook.github.io/flux/docs/overview.html
|
||||
- id: flux-todo-list
|
||||
title: Flux TodoMVC Tutorial
|
||||
href: https://facebook.github.io/flux/docs/todo-list.html
|
||||
|
||||
@@ -35,4 +35,18 @@
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<!-- Contributing Nav -->
|
||||
{% for section in site.data.nav_contributing %}
|
||||
<div class="nav-docs-section">
|
||||
<h3>{{ section.title }}</h3>
|
||||
<ul>
|
||||
{% for item in section.items %}
|
||||
<li>
|
||||
<a href="/react/contributing/{{ item.id }}.html"{% if page.id == item.id %} class="active"{% endif %}>{{ item.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
111
docs/_js/ErrorDecoderComponent.js
Normal file
111
docs/_js/ErrorDecoderComponent.js
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
/* global React ReactDOM errorMap:true */
|
||||
'use strict';
|
||||
|
||||
function replaceArgs(msg, argList) {
|
||||
let argIdx = 0;
|
||||
return msg.replace(/%s/g, function() {
|
||||
const arg = argList[argIdx++];
|
||||
return arg === undefined ? '[missing argument]' : arg;
|
||||
});
|
||||
}
|
||||
|
||||
function urlify(str) {
|
||||
const urlRegex = /(https:\/\/fb\.me\/[a-z\-]+)/g;
|
||||
|
||||
const segments = str.split(urlRegex);
|
||||
|
||||
for (let i = 0; i < segments.length; i++) {
|
||||
if (i % 2 === 1) {
|
||||
segments[i] = (<a key={i} target="_blank" href={segments[i]}>{segments[i]}</a>);
|
||||
}
|
||||
}
|
||||
|
||||
return segments;
|
||||
}
|
||||
|
||||
// ?invariant=123&args[]=foo&args[]=bar
|
||||
function parseQueryString() {
|
||||
const rawQueryString = window.location.search.substring(1);
|
||||
if (!rawQueryString) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let code = '';
|
||||
let args = [];
|
||||
|
||||
const queries = rawQueryString.split('&');
|
||||
for (let i = 0; i < queries.length; i++) {
|
||||
const query = decodeURIComponent(queries[i]);
|
||||
if (query.indexOf('invariant=') === 0) {
|
||||
code = query.slice(10);
|
||||
} else if (query.indexOf('args[]=') === 0) {
|
||||
args.push(query.slice(7));
|
||||
}
|
||||
}
|
||||
|
||||
return [code, args];
|
||||
}
|
||||
|
||||
function ErrorResult(props) {
|
||||
const code = props.code;
|
||||
const errorMsg = props.msg;
|
||||
|
||||
if (!code) {
|
||||
return (
|
||||
<p>When you encounter an error, you'll receive a link to this page for that specific error and we'll show you the full error text.</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>The full text of the error you just encountered is:</p>
|
||||
<code>{urlify(errorMsg)}</code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
class ErrorDecoder extends React.Component {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
this.state = {
|
||||
code: null,
|
||||
errorMsg: '',
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const parseResult = parseQueryString();
|
||||
if (parseResult != null) {
|
||||
const [code, args] = parseResult;
|
||||
if (errorMap[code]) {
|
||||
this.setState({
|
||||
code: code,
|
||||
errorMsg: replaceArgs(errorMap[code], args),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ErrorResult
|
||||
code={this.state.code}
|
||||
msg={this.state.errorMsg}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<ErrorDecoder />,
|
||||
document.querySelector('.error-decoder-container')
|
||||
);
|
||||
@@ -7,7 +7,8 @@ var MarkdownEditor = React.createClass({
|
||||
this.setState({value: this.refs.textarea.value});
|
||||
},
|
||||
rawMarkup: function() {
|
||||
return { __html: marked(this.state.value, {sanitize: true}) };
|
||||
var md = new Remarkable();
|
||||
return { __html: md.render(this.state.value) };
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a web interface for the HTML to JSX converter contained in
|
||||
* `html-jsx-lib.js`.
|
||||
*/
|
||||
;(function() {
|
||||
|
||||
var HELLO_COMPONENT = "\
|
||||
<!-- Hello world -->\n\
|
||||
<div class=\"awesome\" style=\"border: 1px solid red\">\n\
|
||||
<label for=\"name\">Enter your name: </label>\n\
|
||||
<input type=\"text\" id=\"name\" />\n\
|
||||
</div>\n\
|
||||
<p>Enter your HTML here</p>\
|
||||
";
|
||||
|
||||
var HTMLtoJSXComponent = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
outputClassName: 'NewComponent',
|
||||
createClass: true
|
||||
};
|
||||
},
|
||||
onReactClassNameChange: function(evt) {
|
||||
this.setState({ outputClassName: evt.target.value });
|
||||
},
|
||||
onCreateClassChange: function(evt) {
|
||||
this.setState({ createClass: evt.target.checked });
|
||||
},
|
||||
setInput: function(input) {
|
||||
this.setState({ input: input });
|
||||
this.convertToJsx();
|
||||
},
|
||||
convertToJSX: function(input) {
|
||||
var converter = new HTMLtoJSX({
|
||||
outputClassName: this.state.outputClassName,
|
||||
createClass: this.state.createClass
|
||||
});
|
||||
return converter.convert(input);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div id="options">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={this.state.createClass}
|
||||
onChange={this.onCreateClassChange} />
|
||||
Create class
|
||||
</label>
|
||||
<label style={{display: this.state.createClass ? '' : 'none'}}>
|
||||
·
|
||||
Class name:
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.outputClassName}
|
||||
onChange={this.onReactClassNameChange} />
|
||||
</label>
|
||||
</div>
|
||||
<ReactPlayground
|
||||
codeText={HELLO_COMPONENT}
|
||||
renderCode={true}
|
||||
transformer={this.convertToJSX}
|
||||
showCompiledJSTab={false}
|
||||
editorTabTitle="Live HTML Editor"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(<HTMLtoJSXComponent />, document.getElementById('jsxCompiler'));
|
||||
}());
|
||||
@@ -22,7 +22,7 @@ var CodeMirrorEditor = React.createClass({
|
||||
if (IS_MOBILE) return;
|
||||
|
||||
this.editor = CodeMirror.fromTextArea(ReactDOM.findDOMNode(this.refs.editor), {
|
||||
mode: 'javascript',
|
||||
mode: 'jsx',
|
||||
lineNumbers: this.props.lineNumbers,
|
||||
lineWrapping: true,
|
||||
smartIndent: false, // javascript mode does bad things with jsx indents
|
||||
|
||||
23
docs/_layouts/contributing.html
Normal file
23
docs/_layouts/contributing.html
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
layout: default
|
||||
sectionid: contributing
|
||||
---
|
||||
|
||||
<section class="content wrap documentationContent">
|
||||
{% include nav_docs.html %}
|
||||
|
||||
<div class="inner-content">
|
||||
<h1>{{ page.title }}</h1>
|
||||
<div class="subHeader">{{ page.description }}</div>
|
||||
{{ content }}
|
||||
|
||||
<div class="docs-prevnext">
|
||||
{% if page.prev %}
|
||||
<a class="docs-prev" href="/react/contributing/{{ page.prev }}">← Prev</a>
|
||||
{% endif %}
|
||||
{% if page.next %}
|
||||
<a class="docs-next" href="/react/contributing/{{ page.next }}">Next →</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -32,6 +32,8 @@
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script>
|
||||
<script src="/react/js/codemirror.js"></script>
|
||||
<script src="/react/js/javascript.js"></script>
|
||||
<script src="/react/js/xml.js"></script>
|
||||
<script src="/react/js/jsx.js"></script>
|
||||
<script src="/react/js/react.js"></script>
|
||||
<script src="/react/js/react-dom.js"></script>
|
||||
<script src="/react/js/babel-browser.min.js"></script>
|
||||
@@ -48,7 +50,7 @@
|
||||
React
|
||||
</a>
|
||||
<ul class="nav-site nav-site-internal">
|
||||
<li><a href="/react/docs/getting-started.html"{% if page.sectionid == 'docs' or page.sectionid == 'tips' %} class="active"{% endif %}>Docs</a></li>
|
||||
<li><a href="/react/docs/getting-started.html"{% if page.sectionid == 'docs' or page.sectionid == 'tips' or page.sectionid == 'contributing' %} class="active"{% endif %}>Docs</a></li>
|
||||
<li><a href="/react/support.html"{% if page.id == 'support' %} class="active"{% endif %}>Support</a></li>
|
||||
<li><a href="/react/downloads.html"{% if page.id == 'downloads' %} class="active"{% endif %}>Download</a></li>
|
||||
<li><a href="/react/blog/"{% if page.sectionid == 'blog' %} class="active"{% endif %}>Blog</a></li>
|
||||
@@ -109,7 +111,7 @@
|
||||
var js, fjs = d.getElementsByTagName(s)[0];
|
||||
if (d.getElementById(id)) return;
|
||||
js = d.createElement(s); js.id = id;
|
||||
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=623268441017527";
|
||||
js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.6&appId=623268441017527";
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}(document, 'script', 'facebook-jssdk'));
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
module Authors
|
||||
class Generator < Jekyll::Generator
|
||||
def generate(site)
|
||||
site.posts.each do |post|
|
||||
site.posts.docs.each do |post|
|
||||
authors = []
|
||||
if post['author'].kind_of?(Array)
|
||||
for author in post['author']
|
||||
|
||||
@@ -2,14 +2,17 @@ require 'redcarpet'
|
||||
require 'sanitize'
|
||||
|
||||
# Simple converter that is probably better than RedCarpet's built in TOC id
|
||||
# generator (which ends up with things lik id="toc_1"... terrible).
|
||||
# generator (which ends up with things like id="toc_1"... terrible).
|
||||
|
||||
class Redcarpet::Render::HTML
|
||||
def header(title, level)
|
||||
# \p{Common} does not seem to include some of the Japanese alphabets and also includes
|
||||
# some undesired characters like colon and parentheses, so we have to write out the
|
||||
# necessary Unicode scripts individually.
|
||||
clean_title = Sanitize.clean(title)
|
||||
.downcase
|
||||
.gsub(/\s+/, "-")
|
||||
.gsub(/[^A-Za-z0-9\-_.]/, "")
|
||||
.gsub(/[^A-Za-z0-9\-_.\p{Cyrillic}\p{Hangul}\p{Hiragana}\p{Katakana}\p{Han}]/, "")
|
||||
|
||||
return "<h#{level}><a class=\"anchor\" name=\"#{clean_title}\"></a>#{title} <a class=\"hash-link\" href=\"##{clean_title}\">#</a></h#{level}>"
|
||||
end
|
||||
|
||||
@@ -56,7 +56,7 @@ to the DOM.
|
||||
> lightweight description of what the DOM should look like.
|
||||
|
||||
We call this process **reconciliation**. Check out
|
||||
[this jsFiddle](http://jsfiddle.net/fv6RD/3/) to see an example of
|
||||
[this jsFiddle](http://jsfiddle.net/2h6th4ju/) to see an example of
|
||||
reconciliation in action.
|
||||
|
||||
Because this re-render is so fast (around 1ms for TodoMVC), the developer
|
||||
|
||||
@@ -10,7 +10,7 @@ amazed that 600 people requested to be notified when ticket go on sale. This is
|
||||
When we organized the conference, we decided to start small since this is the
|
||||
first React.js conference. Also, we weren't sure what level of demand to expect,
|
||||
so we planned for a single-track, two-day conference on Facebook's campus. The
|
||||
largest room available would accomodate 18 speaking slots and 200 attendees.
|
||||
largest room available would accommodate 18 speaking slots and 200 attendees.
|
||||
The spacial configuration makes it difficult to add a second track and changing
|
||||
venues only two months in advance would be too difficult, so we are deciding to
|
||||
stick with the originally planned format and venue on Facebook's campus.
|
||||
|
||||
259
docs/_posts/2016-04-07-react-v15.md
Normal file
259
docs/_posts/2016-04-07-react-v15.md
Normal file
@@ -0,0 +1,259 @@
|
||||
---
|
||||
title: "React v15.0"
|
||||
author: gaearon
|
||||
---
|
||||
|
||||
We would like to thank the React community for reporting issues and regressions in the release candidates on our [issue tracker](https://github.com/facebook/react/issues/). Over the last few weeks we fixed those issues, and now, after two release candidates, we are excited to finally release the stable version of React 15.
|
||||
|
||||
As a reminder, [we’re switching to major versions](/react/blog/2016/02/19/new-versioning-scheme.html) to indicate that we have been using React in production for a long time. This 15.0 release follows our previous 0.14 version and we’ll continue to follow semver like we’ve been doing since 2013. It’s also worth noting that [we no longer actively support Internet Explorer 8](/react/blog/2016/01/12/discontinuing-ie8-support.html). We believe React will work in its current form there but we will not be prioritizing any efforts to fix new issues that only affect IE8.
|
||||
|
||||
React 15 brings significant improvements to how we interact with the DOM:
|
||||
|
||||
* We are now using `document.createElement` instead of setting `innerHTML` when mounting components. This allows us to get rid of the `data-reactid` attribute on every node and make the DOM lighter. Using `document.createElement` is also faster in modern browsers and fixes a number of edge cases related to SVG elements and running multiple copies of React on the same page.
|
||||
|
||||
* Historically our support for SVG has been incomplete, and many tags and attributes were missing. We heard you, and in React 15 we [added support for all the SVG attributes that are recognized by today’s browsers](https://github.com/facebook/react/pull/6243). If we missed any of the attributes you’d like to use, please [let us know](https://github.com/facebook/react/issues/1657). As a bonus, thanks to using `document.createElement`, we no longer need to maintain a list of SVG tags, so any SVG tags that were previously unsupported should work just fine in React 15.
|
||||
|
||||
* We received some amazing contributions from the community in this release, and we would like to highlight [this pull request](https://github.com/facebook/react/pull/5753) by [Michael Wiencek](https://github.com/mwiencek) in particular. Thanks to Michael’s work, React 15 no longer emits extra `<span>` nodes around the text, making the DOM output much cleaner. This was a longstanding annoyance for React users so it’s exciting to accept this as an outside contribution.
|
||||
|
||||
While this isn’t directly related to the release, we understand that in order to receive more community contributions like Michael’s, we need to communicate our goals and priorities more openly, and review pull requests more decisively. As a first step towards this, we started publishing [React core team weekly meeting notes](https://github.com/reactjs/core-notes) again. We also intend to introduce an RFC process inspired by [Ember RFCs](https://github.com/emberjs/rfcs) so external contributors can have more insight and influence in the future development of React. We will keep you updated about this on our blog.
|
||||
|
||||
We are also experimenting with a new changelog format in this post. Every change now links to the corresponding pull request and mentions the author. Let us know whether you find this useful!
|
||||
|
||||
## Upgrade Guide
|
||||
|
||||
As usual with major releases, React 15 will remove support for some of the patterns deprecated nine months ago in React 0.14. We know changes can be painful (the Facebook codebase has over 20,000 React components, and that’s not even counting React Native), so we always try to make changes gradually in order to minimize the pain.
|
||||
|
||||
If your code is free of warnings when running under React 0.14, upgrading should be easy. The bulk of changes in this release are actually behind the scenes, impacting the way that React interacts with the DOM. The other substantial change is that React now supports the full range of SVG elements and attributes. Beyond that we have a large number of incremental improvements and additional warnings aimed to aid developers. We’ve also laid some groundwork in the core to bring you some new capabilities in future releases.
|
||||
|
||||
See the changelog below for more details.
|
||||
|
||||
## Installation
|
||||
|
||||
We recommend using React from `npm` and using a tool like browserify or webpack to build your code into a single bundle. To install the two packages:
|
||||
|
||||
* `npm install --save react react-dom`
|
||||
|
||||
Remember that by default, React runs extra checks and provides helpful warnings in development mode. When deploying your app, set the `NODE_ENV` environment variable to `production` to use the production build of React which does not include the development warnings and runs significantly faster.
|
||||
|
||||
If you can’t use `npm` yet, we provide pre-built browser builds for your convenience, which are also available in the `react` package on bower.
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-15.0.0.js>
|
||||
Minified build for production: <https://fb.me/react-15.0.0.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-15.0.0.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-15.0.0.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-15.0.0.js>
|
||||
Minified build for production: <https://fb.me/react-dom-15.0.0.min.js>
|
||||
|
||||
## Changelog
|
||||
|
||||
### Major changes
|
||||
|
||||
- #### `document.createElement` is in and `data-reactid` is out
|
||||
|
||||
There were a number of large changes to our interactions with the DOM. One of the most noticeable changes is that we no longer set the `data-reactid` attribute for each DOM node. While this will make it more difficult to know if a website is using React, the advantage is that the DOM is much more lightweight. This change was made possible by us switching to use `document.createElement` on initial render. Previously we would generate a large string of HTML and then set `node.innerHTML`. At the time, this was decided to be faster than using `document.createElement` for the majority of cases and browsers that we supported. Browsers have continued to improve and so overwhelmingly this is no longer true. By using `createElement` we can make other parts of React faster. The ids were used to map back from events to the original React component, meaning we had to do a bunch of work on every event, even though we cached this data heavily. As we’ve all experienced, caching and in particularly invalidating caches, can be error prone and we saw many hard to reproduce issues over the years as a result. Now we can build up a direct mapping at render time since we already have a handle on the node.
|
||||
|
||||
**Note:** `data-reactid` is still present for server-rendered content, however it is much smaller than before and is simply an auto-incrementing counter.
|
||||
|
||||
<small>[@spicyj](https://github.com/spicyj) in [#5205](https://github.com/facebook/react/pull/5205)</small>
|
||||
|
||||
- #### No more extra `<span>`s
|
||||
|
||||
Another big change with our DOM interaction is how we render text blocks. Previously you may have noticed that React rendered a lot of extra `<span>`s. For example, in our most basic example on the home page we render `<div>Hello {this.props.name}</div>`, resulting in markup that contained 2 `<span>`s. Now we’ll render plain text nodes interspersed with comment nodes that are used for demarcation. This gives us the same ability to update individual pieces of text, without creating extra nested nodes. Very few people have depended on the actual markup generated here so it’s likely you are not impacted. However if you were targeting these `<span>`s in your CSS, you will need to adjust accordingly. You can always render them explicitly in your components.
|
||||
|
||||
<small>[@mwiencek](https://github.com/mwiencek) in [#5753](https://github.com/facebook/react/pull/5753)</small>
|
||||
|
||||
- #### Rendering `null` now uses comment nodes
|
||||
|
||||
We’ve also made use of these comment nodes to change what `null` renders to. Rendering to `null` was a feature we added in React 0.11 and was implemented by rendering `<noscript>` elements. By rendering to comment nodes now, there’s a chance some of your CSS will be targeting the wrong thing, specifically if you are making use of `:nth-child` selectors. React’s use of the `<noscript>` tag has always been considered an implementation detail of how React targets the DOM. We believe they are safe changes to make without going through a release with warnings detailing the subtle differences as they are details that should not be depended upon. Additionally, we have seen that these changes have improved React performance for many typical applications.
|
||||
|
||||
<small>[@spicyj](https://github.com/spicyj) in [#5451](https://github.com/facebook/react/pull/5451)</small>
|
||||
|
||||
- #### Functional components can now return `null` too
|
||||
|
||||
We added support for [defining stateless components as functions](/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components) in React 0.14. However, React 0.14 still allowed you to define a class component without extending `React.Component` or using `React.createClass()`, so [we couldn’t reliably tell if your component is a function or a class](https://github.com/facebook/react/issues/5355), and did not allow returning `null` from it. This issue is solved in React 15, and you can now return `null` from any component, whether it is a class or a function.
|
||||
|
||||
<small>[@jimfb](https://github.com/jimfb) in [#5884](https://github.com/facebook/react/pull/5884)</small>
|
||||
|
||||
- #### Improved SVG support
|
||||
|
||||
All SVG tags are now fully supported. (Uncommon SVG tags are not present on the `React.DOM` element helper, but JSX and `React.createElement` work on all tag names.) All SVG attributes that are implemented by the browsers should be supported too. If you find any attributes that we have missed, please [let us know in this issue](https://github.com/facebook/react/issues/1657).
|
||||
|
||||
<small>[@zpao](https://github.com/zpao) in [#6243](https://github.com/facebook/react/pull/6243)</small>
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- #### No more extra `<span>`s
|
||||
|
||||
It’s worth calling out the DOM structure changes above again, in particular the change from `<span>`s. In the course of updating the Facebook codebase, we found a very small amount of code that was depending on the markup that React generated. Some of these cases were integration tests like WebDriver which were doing very specific XPath queries to target nodes. Others were simply tests using `ReactDOM.renderToStaticMarkup` and comparing markup. Again, there were a very small number of changes that had to be made, but we don’t want anybody to be blindsided. We encourage everybody to run their test suites when upgrading and consider alternative approaches when possible. One approach that will work for some cases is to explicitly use `<span>`s in your `render` method.
|
||||
|
||||
<small>[@mwiencek](https://github.com/mwiencek) in [#5753](https://github.com/facebook/react/pull/5753)</small>
|
||||
|
||||
- #### `React.cloneElement()` now resolves `defaultProps`
|
||||
|
||||
We fixed a bug in `React.cloneElement()` that some components may rely on. If some of the `props` received by `cloneElement()` are `undefined`, it used to return an element with `undefined` values for those props. In React 15, we’re changing it to be consistent with `createElement()`. Now any `undefined` props passed to `cloneElement()` are resolved to the corresponding component’s `defaultProps`. Only one of our 20,000 React components was negatively affected by this so we feel comfortable releasing this change without keeping the old behavior for another release cycle.
|
||||
|
||||
<small>[@truongduy134](https://github.com/truongduy134) in [#5997](https://github.com/facebook/react/pull/5997)</small>
|
||||
|
||||
- #### `ReactPerf.getLastMeasurements()` is opaque
|
||||
|
||||
This change won’t affect applications but may break some third-party tools. We are [revamping `ReactPerf` implementation](https://github.com/facebook/react/pull/6046) and plan to release it during the 15.x cycle. The internal performance measurement format is subject to change so, for the time being, we consider the return value of `ReactPerf.getLastMeasurements()` an opaque data structure that should not be relied upon.
|
||||
|
||||
<small>[@gaearon](https://github.com/gaearon) in [#6286](https://github.com/facebook/react/pull/6286)</small>
|
||||
|
||||
- #### Removed deprecations
|
||||
|
||||
These deprecations were introduced nine months ago in v0.14 with a warning and are removed:
|
||||
|
||||
- Deprecated APIs are removed from the `React` top-level export: `findDOMNode`, `render`, `renderToString`, `renderToStaticMarkup`, and `unmountComponentAtNode`. As a reminder, they are now available on `ReactDOM` and `ReactDOMServer`.
|
||||
<small>[@jimfb](https://github.com/jimfb) in [#5832](https://github.com/facebook/react/pull/5832)</small>
|
||||
|
||||
- Deprecated addons are removed: `batchedUpdates` and `cloneWithProps`.
|
||||
<small>[@jimfb](https://github.com/jimfb) in [#5859](https://github.com/facebook/react/pull/5859), [@zpao](https://github.com/zpao) in [#6016](https://github.com/facebook/react/pull/6016)</small>
|
||||
|
||||
- Deprecated component instance methods are removed: `setProps`, `replaceProps`, and `getDOMNode`.
|
||||
<small>[@jimfb](https://github.com/jimfb) in [#5570](https://github.com/facebook/react/pull/5570)</small>
|
||||
|
||||
- Deprecated CommonJS `react/addons` entry point is removed. As a reminder, you should use separate `react-addons-*` packages instead. This only applies if you use the CommonJS builds.
|
||||
<small>[@gaearon](https://github.com/gaearon) in [#6285](https://github.com/facebook/react/pull/6285)</small>
|
||||
|
||||
- Passing `children` to void elements like `<input>` was deprecated, and now throws an error.
|
||||
<small>[@jonhester](https://github.com/jonhester) in [#3372](https://github.com/facebook/react/pull/3372)</small>
|
||||
|
||||
- React-specific properties on DOM `refs` (e.g. `this.refs.div.props`) were deprecated, and are removed now.
|
||||
<small>[@jimfb](https://github.com/jimfb) in [#5495](https://github.com/facebook/react/pull/5495)</small>
|
||||
|
||||
### New deprecations, introduced with a warning
|
||||
|
||||
Each of these changes will continue to work as before with a new warning until the release of React 16 so you can upgrade your code gradually.
|
||||
|
||||
- `LinkedStateMixin` and `valueLink` are now deprecated due to very low popularity. If you need this, you can use a wrapper component that implements the same behavior: [react-linked-input](https://www.npmjs.com/package/react-linked-input).
|
||||
<small>[@jimfb](https://github.com/jimfb) in [#6127](https://github.com/facebook/react/pull/6127)</small>
|
||||
|
||||
- Future versions of React will treat `<input value={null}>` as a request to clear the input. However, React 0.14 has been ignoring `value={null}`. React 15 warns you on a `null` input value and offers you to clarify your intention. To fix the warning, you may explicitly pass an empty string to clear a controlled input, or pass `undefined` to make the input uncontrolled.
|
||||
<small>[@antoaravinth](https://github.com/antoaravinth) in [#5048](https://github.com/facebook/react/pull/5048)</small>
|
||||
|
||||
- `ReactPerf.printDOM()` was renamed to `ReactPerf.printOperations()`, and `ReactPerf.getMeasurementsSummaryMap()` was renamed to `ReactPerf.getWasted()`.
|
||||
<small>[@gaearon](https://github.com/gaearon) in [#6287](https://github.com/facebook/react/pull/6287)</small>
|
||||
|
||||
### New helpful warnings
|
||||
|
||||
- If you use a minified copy of the _development_ build, React DOM kindly encourages you to use the faster production build instead.
|
||||
<small>[@spicyj](https://github.com/spicyj) in [#5083](https://github.com/facebook/react/pull/5083)</small>
|
||||
|
||||
- React DOM: When specifying a unit-less CSS value as a string, a future version will not add `px` automatically. This version now warns in this case (ex: writing `style={{'{{'}}width: '300'}}`. Unitless *number* values like `width: 300` are unchanged.
|
||||
<small>[@pluma](https://github.com/pluma) in [#5140](https://github.com/facebook/react/pull/5140)</small>
|
||||
|
||||
- Synthetic Events will now warn when setting and accessing properties (which will not get cleared appropriately), as well as warn on access after an event has been returned to the pool.
|
||||
<small>[@kentcdodds](https://github.com/kentcdodds) in [#5940](https://github.com/facebook/react/pull/5940) and [@koba04](https://github.com/koba04) in [#5947](https://github.com/facebook/react/pull/5947)</small>
|
||||
|
||||
- Elements will now warn when attempting to read `ref` and `key` from the props.
|
||||
<small>[@prometheansacrifice](https://github.com/prometheansacrifice) in [#5744](https://github.com/facebook/react/pull/5744)</small>
|
||||
|
||||
- React will now warn if you pass a different `props` object to `super()` in the constructor.
|
||||
<small>[@prometheansacrifice](https://github.com/prometheansacrifice) in [#5346](https://github.com/facebook/react/pull/5346)</small>
|
||||
|
||||
- React will now warn if you call `setState()` inside `getChildContext()`.
|
||||
<small>[@raineroviir](https://github.com/raineroviir) in [#6121](https://github.com/facebook/react/pull/6121)</small>
|
||||
|
||||
- React DOM now attempts to warn for mistyped event handlers on DOM elements, such as `onclick` which should be `onClick`.
|
||||
<small>[@ali](https://github.com/ali) in [#5361](https://github.com/facebook/react/pull/5361)</small>
|
||||
|
||||
- React DOM now warns about `NaN` values in `style`.
|
||||
<small>[@jontewks](https://github.com/jontewks) in [#5811](https://github.com/facebook/react/pull/5811)</small>
|
||||
|
||||
- React DOM now warns if you specify both `value` and `defaultValue` for an input.
|
||||
<small>[@mgmcdermott](https://github.com/mgmcdermott) in [#5823](https://github.com/facebook/react/pull/5823)</small>
|
||||
|
||||
- React DOM now warns if an input switches between being controlled and uncontrolled.
|
||||
<small>[@TheBlasfem](https://github.com/TheBlasfem) in [#5864](https://github.com/facebook/react/pull/5864)</small>
|
||||
|
||||
- React DOM now warns if you specify `onFocusIn` or `onFocusOut` handlers as they are unnecessary in React.
|
||||
<small>[@jontewks](https://github.com/jontewks) in [#6296](https://github.com/facebook/react/pull/6296)</small>
|
||||
|
||||
- React now prints a descriptive error message when you pass an invalid callback as the last argument to `ReactDOM.render()`, `this.setState()`, or `this.forceUpdate()`.
|
||||
<small>[@conorhastings](https://github.com/conorhastings) in [#5193](https://github.com/facebook/react/pull/5193) and [@gaearon](https://github.com/gaearon) in [#6310](https://github.com/facebook/react/pull/6310)</small>
|
||||
|
||||
- Add-Ons: `TestUtils.Simulate()` now prints a helpful message if you attempt to use it with shallow rendering.
|
||||
<small>[@conorhastings](https://github.com/conorhastings) in [#5358](https://github.com/facebook/react/pull/5358)</small>
|
||||
|
||||
- PropTypes: `arrayOf()` and `objectOf()` provide better error messages for invalid arguments.
|
||||
<small>[@chicoxyzzy](https://github.com/chicoxyzzy) in [#5390](https://github.com/facebook/react/pull/5390)</small>
|
||||
|
||||
### Notable bug fixes
|
||||
|
||||
- Fixed multiple small memory leaks.
|
||||
<small>[@spicyj](https://github.com/spicyj) in [#4983](https://github.com/facebook/react/pull/4983) and [@victor-homyakov](https://github.com/victor-homyakov) in [#6309](https://github.com/facebook/react/pull/6309)</small>
|
||||
|
||||
- Input events are handled more reliably in IE 10 and IE 11; spurious events no longer fire when using a placeholder.
|
||||
<small>[@jquense](https://github.com/jquense) in [#4051](https://github.com/facebook/react/pull/4051)</small>
|
||||
|
||||
- The `componentWillReceiveProps()` lifecycle method is now consistently called when `context` changes.
|
||||
<small>[@milesj](https://github.com/milesj) in [#5787](https://github.com/facebook/react/pull/5787)</small>
|
||||
|
||||
- `React.cloneElement()` doesn’t append slash to an existing `key` when used inside `React.Children.map()`.
|
||||
<small>[@ianobermiller](https://github.com/ianobermiller) in [#5892](https://github.com/facebook/react/pull/5892)</small>
|
||||
|
||||
- React DOM now supports the `cite` and `profile` HTML attributes.
|
||||
<small>[@AprilArcus](https://github.com/AprilArcus) in [#6094](https://github.com/facebook/react/pull/6094) and [@saiichihashimoto](https://github.com/saiichihashimoto) in [#6032](https://github.com/facebook/react/pull/6032)</small>
|
||||
|
||||
- React DOM now supports `cssFloat`, `gridRow` and `gridColumn` CSS properties.
|
||||
<small>[@stevenvachon](https://github.com/stevenvachon) in [#6133](https://github.com/facebook/react/pull/6133) and [@mnordick](https://github.com/mnordick) in [#4779](https://github.com/facebook/react/pull/4779)</small>
|
||||
|
||||
- React DOM now correctly handles `borderImageOutset`, `borderImageWidth`, `borderImageSlice`, `floodOpacity`, `strokeDasharray`, and `strokeMiterlimit` as unitless CSS properties.
|
||||
<small>[@rofrischmann](https://github.com/rofrischmann) in [#6210](https://github.com/facebook/react/pull/6210) and [#6270](https://github.com/facebook/react/pull/6270)</small>
|
||||
|
||||
- React DOM now supports the `onAnimationStart`, `onAnimationEnd`, `onAnimationIteration`, `onTransitionEnd`, and `onInvalid` events. Support for `onLoad` has been added to `object` elements.
|
||||
<small>[@tomduncalf](https://github.com/tomduncalf) in [#5187](https://github.com/facebook/react/pull/5187), [@milesj](https://github.com/milesj) in [#6005](https://github.com/facebook/react/pull/6005), and [@ara4n](https://github.com/ara4n) in [#5781](https://github.com/facebook/react/pull/5781)</small>
|
||||
|
||||
- React DOM now defaults to using DOM attributes instead of properties, which fixes a few edge case bugs. Additionally the nullification of values (ex: `href={null}`) now results in the forceful removal, no longer trying to set to the default value used by browsers in the absence of a value.
|
||||
<small>[@syranide](https://github.com/syranide) in [#1510](https://github.com/facebook/react/pull/1510)</small>
|
||||
|
||||
- React DOM does not mistakingly coerce `children` to strings for Web Components.
|
||||
<small>[@jimfb](https://github.com/jimfb) in [#5093](https://github.com/facebook/react/pull/5093)</small>
|
||||
|
||||
- React DOM now correctly normalizes SVG `<use>` events.
|
||||
<small>[@edmellum](https://github.com/edmellum) in [#5720](https://github.com/facebook/react/pull/5720)</small>
|
||||
|
||||
- React DOM does not throw if a `<select>` is unmounted while its `onChange` handler is executing.
|
||||
<small>[@sambev](https://github.com/sambev) in [#6028](https://github.com/facebook/react/pull/6028)</small>
|
||||
|
||||
- React DOM does not throw in Windows 8 apps.
|
||||
<small>[@Andrew8xx8](https://github.com/Andrew8xx8) in [#6063](https://github.com/facebook/react/pull/6063)</small>
|
||||
|
||||
- React DOM does not throw when asynchronously unmounting a child with a `ref`.
|
||||
<small>[@yiminghe](https://github.com/yiminghe) in [#6095](https://github.com/facebook/react/pull/6095)</small>
|
||||
|
||||
- React DOM no longer forces synchronous layout because of scroll position tracking.
|
||||
<small>[@syranide](https://github.com/syranide) in [#2271](https://github.com/facebook/react/pull/2271)</small>
|
||||
|
||||
- `Object.is` is used in a number of places to compare values, which leads to fewer false positives, especially involving `NaN`. In particular, this affects the `shallowCompare` add-on.
|
||||
<small>[@chicoxyzzy](https://github.com/chicoxyzzy) in [#6132](https://github.com/facebook/react/pull/6132)</small>
|
||||
|
||||
- Add-Ons: ReactPerf no longer instruments adding or removing an event listener because they don’t really touch the DOM due to event delegation.
|
||||
<small>[@antoaravinth](https://github.com/antoaravinth) in [#5209](https://github.com/facebook/react/pull/5209)</small>
|
||||
|
||||
### Other improvements
|
||||
|
||||
- React now uses `loose-envify` instead of `envify` so it installs fewer transitive dependencies.
|
||||
<small>[@qerub](https://github.com/qerub) in [#6303](https://github.com/facebook/react/pull/6303)</small>
|
||||
|
||||
- Shallow renderer now exposes `getMountedInstance()`.
|
||||
<small>[@glenjamin](https://github.com/glenjamin) in [#4918](https://github.com/facebook/react/pull/4918)</small>
|
||||
|
||||
- Shallow renderer now returns the rendered output from `render()`.
|
||||
<small>[@simonewebdesign](https://github.com/simonewebdesign) in [#5411](https://github.com/facebook/react/pull/5411)</small>
|
||||
|
||||
- React no longer depends on ES5 *shams* for `Object.create` and `Object.freeze` in older environments. It still, however, requires ES5 *shims* in those environments.
|
||||
<small>[@dgreensp](https://github.com/dgreensp) in [#4959](https://github.com/facebook/react/pull/4959)</small>
|
||||
|
||||
- React DOM now allows `data-` attributes with names that start with numbers.
|
||||
<small>[@nLight](https://github.com/nLight) in [#5216](https://github.com/facebook/react/pull/5216)</small>
|
||||
|
||||
- React DOM adds a new `suppressContentEditableWarning` prop for components like [Draft.js](https://facebook.github.io/draft-js/) that intentionally manage `contentEditable` children with React.
|
||||
<small>[@mxstbr](https://github.com/mxstbr) in [#6112](https://github.com/facebook/react/pull/6112)</small>
|
||||
|
||||
- React improves the performance for `createClass()` on complex specs.
|
||||
<small>[@spicyj](https://github.com/spicyj) in [#5550](https://github.com/facebook/react/pull/5550)</small>
|
||||
34
docs/_posts/2016-04-08-react-v15.0.1.md
Normal file
34
docs/_posts/2016-04-08-react-v15.0.1.md
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: "React v15.0.1"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
Yesterday afternoon we shipped v15.0.0 and quickly got some feedback about a couple of issues. We apologize for these problems and we've been working since then to make sure we get fixes into your hands as quickly as possible.
|
||||
|
||||
The first of these issues is related to the removal of an undocumented API. This API was added to enable [JSX Spread Attributes](/react/docs/jsx-spread.html) in our JS compile tools (react-tools, JSXTransformer) before `Object.assign` was standard. When we stopped supporting these tools last year, we kept the API there to catch the longer tail of people using those tools. Meanwhile we moved to using Babel and encouraged others to do the same. Babel will typically compile the spread use to an `_extends` helper, which will use `Object.assign`. We did not properly research other compilation tools before deciding to remove the API in v15. Specifically, TypeScript and coffee-react are two popular packages using `React.__spread`, as well as reactify which still makes use react-tools. In order to make sure that code compiled with these tools is not broken, we will be restoring the `React.__spread` API and adding a warning. It will be removed in the future so if you maintain a project making using of it, we encourage you to compile to `Object.assign` directly or a similar helper function.
|
||||
|
||||
The second issue resulted in cursor position being lost in controlled inputs. We merged a pull request earlier this week to fix a separate regression from v0.14. Our goal was to target `<option>` elements but we ended up targeting all interactions with `value` properties. Unfortunately we didn't test it as thoroughly as we thought. We backed out the offending change and fixed the issue in different way which doesn't have the same problem.
|
||||
|
||||
We apologize if you installed 15.0.0 and have encountered these issues yourselves.
|
||||
|
||||
As usual, you can get install the `react` package via npm or download a browser bundle.
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-15.0.1.js>
|
||||
Minified build for production: <https://fb.me/react-15.0.1.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-15.0.1.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-15.0.1.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-15.0.1.js>
|
||||
Minified build for production: <https://fb.me/react-dom-15.0.1.min.js>
|
||||
|
||||
## Changelog
|
||||
|
||||
### React
|
||||
- Restore `React.__spread` API to unbreak code compiled with some tools making use of this undocumented API. It is now officially deprecated.
|
||||
<small>[@zpao](https://github.com/zpao) in [#6444](https://github.com/facebook/react/pull/6444)</small>
|
||||
|
||||
### ReactDOM
|
||||
- Fixed issue resulting in loss of cursor position in controlled inputs.
|
||||
<small>[@spicyj](https://github.com/spicyj) in [#6449](https://github.com/facebook/react/pull/6449)</small>
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: "Introducing React's Error Code System"
|
||||
author: keyanzhang
|
||||
---
|
||||
|
||||
Building a better developer experience has been one of the things that React deeply cares about, and a crucial part of it is to detect anti-patterns/potential errors early and provide helpful error messages when things (may) go wrong. However, most of these only exist in development mode; in production, we avoid having extra expensive assertions and sending down full error messages in order to reduce the number of bytes sent over the wire.
|
||||
|
||||
Prior to this release, we stripped out error messages at build-time and this is why you might have seen this message in production:
|
||||
|
||||
> Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.
|
||||
|
||||
In order to make debugging in production easier, we're introducing an Error Code System in [15.2.0](https://github.com/facebook/react/releases/tag/v15.2.0). We developed a [gulp script](https://github.com/facebook/react/blob/master/scripts/error-codes/gulp-extract-errors.js) that collects all of our `invariant` error messages and folds them to a [JSON file](https://github.com/facebook/react/blob/master/scripts/error-codes/codes.json), and at build-time Babel uses the JSON to [rewrite](https://github.com/facebook/react/blob/master/scripts/error-codes/dev-expression-with-codes.js) our `invariant` calls in production to reference the corresponding error IDs. Now when things go wrong in production, the error that React throws will contain a URL with an error ID and relevant information. The URL will point you to a page in our documentation where the original error message gets reassembled.
|
||||
|
||||
While we hope you don't see errors often, you can see how it works [here](/react/docs/error-decoder.html?invariant=109&args[]=Foo). This is what the same error from above will look like:
|
||||
|
||||
> Minified React error #109; visit https://facebook.github.io/react/docs/error-decoder.html?invariant=109&args[]=Foo for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
|
||||
|
||||
We do this so that the developer experience is as good as possible, while also keeping the production bundle size as small as possible. This feature shouldn't require any changes on your side — use the `min.js` files in production or bundle your application code with `process.env.NODE_ENV === 'production'` and you should be good to go!
|
||||
614
docs/_posts/2016-07-13-mixins-considered-harmful.md
Normal file
614
docs/_posts/2016-07-13-mixins-considered-harmful.md
Normal file
@@ -0,0 +1,614 @@
|
||||
---
|
||||
title: "Mixins Considered Harmful"
|
||||
author: gaearon
|
||||
---
|
||||
|
||||
“How do I share the code between several components?” is one of the first questions that people ask when they learn React. Our answer has always been to use component composition for code reuse. You can define a component and use it in several other components.
|
||||
|
||||
It is not always obvious how a certain pattern can be solved with composition. React is influenced by functional programming but it came into the field that was dominated by object-oriented libraries. It was hard for engineers both inside and outside of Facebook to give up on the patterns they were used to.
|
||||
|
||||
To ease the initial adoption and learning, we included certain escape hatches into React. The mixin system was one of those escape hatches, and its goal was to give you a way to reuse code between components when you aren’t sure how to solve the same problem with composition.
|
||||
|
||||
Three years passed since React was released. The landscape has changed. Multiple view libraries now adopt a component model similar to React. Using composition over inheritance to build declarative user interfaces is no longer a novelty. We are also more confident in the React component model, and we have seen many creative uses of it both internally and in the community.
|
||||
|
||||
In this post, we will consider the problems commonly caused by mixins. Then we will suggest several alternative patterns for the same use cases. We have found those patterns to scale better with the complexity of the codebase than mixins.
|
||||
|
||||
## Why Mixins are Broken
|
||||
|
||||
At Facebook, React usage has grown from a few components to thousands of them. This gives us a window into how people use React. Thanks to declarative rendering and top-down data flow, many teams were able to fix a bunch of bugs while shipping new features as they adopted React.
|
||||
|
||||
However it’s inevitable that some of our code using React gradually became incomprehensible. Occasionally, the React team would see groups of components in different projects that people were afraid to touch. These components were too easy to break accidentally, were confusing to new developers, and eventually became just as confusing to the people who wrote them in the first place. Much of this confusion was caused by mixins. At the time, I wasn’t working at Facebook but I came to the [same conclusions](https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750) after writing my fair share of terrible mixins.
|
||||
|
||||
This doesn’t mean that mixins themselves are bad. People successfully employ them in different languages and paradigms, including some functional languages. At Facebook, we extensively use traits in Hack which are fairly similar to mixins. Nevertheless, we think that mixins are unnecessary and problematic in React codebases. Here’s why.
|
||||
|
||||
### Mixins introduce implicit dependencies
|
||||
|
||||
Sometimes a component relies on a certain method defined in the mixin, such as `getClassName()`. Sometimes it’s the other way around, and mixin calls a method like `renderHeader()` on the component. JavaScript is a dynamic language so it’s hard to enforce or document these dependencies.
|
||||
|
||||
Mixins break the common and usually safe assumption that you can rename a state key or a method by searching for its occurrences in the component file. You might write a stateful component and then your coworker might add a mixin that reads this state. In a few months, you might want to move that state up to the parent component so it can be shared with a sibling. Will you remember to update the mixin to read a prop instead? What if, by now, other components also use this mixin?
|
||||
|
||||
These implicit dependencies make it hard for new team members to contribute to a codebase. A component’s `render()` method might reference some method that isn’t defined on the class. Is it safe to remove? Perhaps it’s defined in one of the mixins. But which one of them? You need to scroll up to the mixin list, open each of those files, and look for this method. Worse, mixins can specify their own mixins, so the search can be deep.
|
||||
|
||||
Often, mixins come to depend on other mixins, and removing one of them breaks the other. In these situations it is very tricky to tell how the data flows in and out of mixins, and what their dependency graph looks like. Unlike components, mixins don’t form a hierarchy: they are flattened and operate in the same namespace.
|
||||
|
||||
### Mixins cause name clashes
|
||||
|
||||
There is no guarantee that two particular mixins can be used together. For example, if `FluxListenerMixin` defines `handleChange()` and `WindowSizeMixin` defines `handleChange()`, you can’t use them together. You also can’t define a method with this name on your own component.
|
||||
|
||||
It’s not a big deal if you control the mixin code. When you have a conflict, you can rename that method on one of the mixins. However it’s tricky because some components or other mixins may already be calling this method directly, and you need to find and fix those calls as well.
|
||||
|
||||
If you have a name conflict with a mixin from a third party package, you can’t just rename a method on it. Instead, you have to use awkward method names on your component to avoid clashes.
|
||||
|
||||
The situation is no better for mixin authors. Even adding a new method to a mixin is always a potentially breaking change because a method with the same name might already exist on some of the components using it, either directly or through another mixin. Once written, mixins are hard to remove or change. Bad ideas don’t get refactored away because refactoring is too risky.
|
||||
|
||||
### Mixins cause snowballing complexity
|
||||
|
||||
Even when mixins start out simple, they tend to become complex over time. The example below is based on a real scenario I’ve seen play out in a codebase.
|
||||
|
||||
A component needs some state to track mouse hover. To keep this logic reusable, you might extract `handleMouseEnter()`, `handleMouseLeave()` and `isHovering()` into a `HoverMixin`. Next, somebody needs to implement a tooltip. They don’t want to duplicate the logic in `HoverMixin` so they create a `TooltipMixin` that uses `HoverMixin`. `TooltipMixin` reads `isHovering()` provided by `HoverMixin` in its `componentDidUpdate()` and either shows or hides the tooltip.
|
||||
|
||||
A few months later, somebody wants to make the tooltip direction configurable. In an effort to avoid code duplication, they add support for a new optional method called `getTooltipOptions()` to `TooltipMixin`. By this time, components that show popovers also use `HoverMixin`. However popovers need a different hover delay. To solve this, somebody adds support for an optional `getHoverOptions()` method and implements it in `TooltipMixin`. Those mixins are now tightly coupled.
|
||||
|
||||
This is fine while there are no new requirements. However this solution doesn’t scale well. What if you want to support displaying multiple tooltips in a single component? You can’t define the same mixin twice in a component. What if the tooltips need to be displayed automatically in a guided tour instead of on hover? Good luck decoupling `TooltipMixin` from `HoverMixin`. What if you need to support the case where the hover area and the tooltip anchor are located in different components? You can’t easily hoist the state used by mixin up into the parent component. Unlike components, mixins don’t lend themselves naturally to such changes.
|
||||
|
||||
Every new requirement makes the mixins harder to understand. Components using the same mixin become increasingly coupled with time. Any new capability gets added to all of the components using that mixin. There is no way to split a “simpler” part of the mixin without either duplicating the code or introducing more dependencies and indirection between mixins. Gradually, the encapsulation boundaries erode, and since it’s hard to change or remove the existing mixins, they keep getting more abstract until nobody understands how they work.
|
||||
|
||||
These are the same problems we faced building apps before React. We found that they are solved by declarative rendering, top-down data flow, and encapsulated components. At Facebook, we have been migrating our code to use alternative patterns to mixins, and we are generally happy with the results. You can read about those patterns below.
|
||||
|
||||
## Migrating from Mixins
|
||||
|
||||
Let’s make it clear that mixins are not technically deprecated. If you use `React.createClass()`, you may keep using them. We only say that they didn’t work well for us, and so we won’t recommend using them in the future.
|
||||
|
||||
Every section below corresponds to a mixin usage pattern that we found in the Facebook codebase. For each of them, we describe the problem and a solution that we think works better than mixins. The examples are written in ES5 but once you don’t need mixins, you can switch to ES6 classes if you’d like.
|
||||
|
||||
We hope that you find this list helpful. Please let us know if we missed important use cases so we can either amend the list or be proven wrong!
|
||||
|
||||
### Performance Optimizations
|
||||
|
||||
One of the most commonly used mixins is [`PureRenderMixin`](/react/docs/pure-render-mixin.html). You might be using it in some components to [prevent unnecessary re-renders](/react/docs/advanced-performance.html#shouldcomponentupdate-in-action) when the props and state are shallowly equal to the previous props and state:
|
||||
|
||||
```javascript
|
||||
var PureRenderMixin = require('react-addons-pure-render-mixin');
|
||||
|
||||
var Button = React.createClass({
|
||||
mixins: [PureRenderMixin],
|
||||
|
||||
// ...
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
#### Solution
|
||||
|
||||
To express the same without mixins, you can use the [`shallowCompare`](/react/docs/shallow-compare.html) function directly instead:
|
||||
|
||||
```js
|
||||
var shallowCompare = require('react-addons-shallow-compare');
|
||||
|
||||
var Button = React.createClass({
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
return shallowCompare(this, nextProps, nextState);
|
||||
},
|
||||
|
||||
// ...
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
If you use a custom mixin implementing a `shouldComponentUpdate` function with different algorithm, we suggest exporting just that single function from a module and calling it directly from your components.
|
||||
|
||||
We understand that more typing can be annoying. For the most common case, we plan to [introduce a new base class](https://github.com/facebook/react/pull/7195) called `React.PureComponent` in the next minor release. It uses the same shallow comparison as `PureRenderMixin` does today.
|
||||
|
||||
### Subscriptions and Side Effects
|
||||
|
||||
The second most common type of mixins that we encountered are mixins that subscribe a React component to a third-party data source. Whether this data source is a Flux Store, an Rx Observable, or something else, the pattern is very similar: the subscription is created in `componentDidMount`, destroyed in `componentWillUnmount`, and the change handler calls `this.setState()`.
|
||||
|
||||
```javascript
|
||||
var SubscriptionMixin = {
|
||||
getInitialState: function() {
|
||||
return {
|
||||
comments: DataSource.getComments()
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
DataSource.addChangeListener(this.handleChange);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
DataSource.removeChangeListener(this.handleChange);
|
||||
},
|
||||
|
||||
handleChange: function() {
|
||||
this.setState({
|
||||
comments: DataSource.getComments()
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var CommentList = React.createClass({
|
||||
mixins: [SubscriptionMixin],
|
||||
|
||||
render: function() {
|
||||
// Reading comments from state managed by mixin.
|
||||
var comments = this.state.comments;
|
||||
return (
|
||||
<div>
|
||||
{comments.map(function(comment) {
|
||||
return <Comment comment={comment} key={comment.id} />
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = CommentList;
|
||||
```
|
||||
|
||||
#### Solution
|
||||
|
||||
If there is just one component subscribed to this data source, it is fine to embed the subscription logic right into the component. Avoid premature abstractions.
|
||||
|
||||
If several components used this mixin to subscribe to a data source, a nice way to avoid repetition is to use a pattern called [“higher-order components”](https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750). It can sound intimidating so we will take a closer look at how this pattern naturally emerges from the component model.
|
||||
|
||||
#### Higher-Order Components Explained
|
||||
|
||||
Let’s forget about React for a second. Consider these two functions that add and multiply numbers, logging the results as they do that:
|
||||
|
||||
```js
|
||||
function addAndLog(x, y) {
|
||||
var result = x + y;
|
||||
console.log('result:', result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function multiplyAndLog(x, y) {
|
||||
var result = x * y;
|
||||
console.log('result:', result);
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
These two functions are not very useful but they help us demonstrate a pattern that we can later apply to components.
|
||||
|
||||
Let’s say that we want to extract the logging logic out of these functions without changing their signatures. How can we do this? An elegant solution is to write a [higher-order function](https://en.wikipedia.org/wiki/Higher-order_function), that is, a function that takes a function as an argument and returns a function.
|
||||
|
||||
Again, it sounds more intimidating than it really is:
|
||||
|
||||
```js
|
||||
function withLogging(wrappedFunction) {
|
||||
// Return a function with the same API...
|
||||
return function(x, y) {
|
||||
// ... that calls the original function
|
||||
var result = wrappedFunction(x, y);
|
||||
// ... but also logs its result!
|
||||
console.log('result:', result);
|
||||
return result;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The `withLogging` higher-order function lets us write `add` and `multiply` without the logging statements, and later wrap them to get `addAndLog` and `multiplyAndLog` with exactly the same signatures as before:
|
||||
|
||||
```js
|
||||
function add(x, y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
function multiply(x, y) {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
function withLogging(wrappedFunction) {
|
||||
return function(x, y) {
|
||||
var result = wrappedFunction(x, y);
|
||||
console.log('result:', result);
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
// Equivalent to writing addAndLog by hand:
|
||||
var addAndLog = withLogging(add);
|
||||
|
||||
// Equivalent to writing multiplyAndLog by hand:
|
||||
var multiplyAndLog = withLogging(multiply);
|
||||
```
|
||||
|
||||
Higher-order components are a very similar pattern, but applied to components in React. We will apply this transformation from mixins in two steps.
|
||||
|
||||
As a first step, we will split our `CommentList` component in two, a child and a parent. The child will be only concerned with rendering the comments. The parent will set up the subscription and pass the up-to-date data to the child via props.
|
||||
|
||||
```js
|
||||
// This is a child component.
|
||||
// It only renders the comments it receives as props.
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
// Note: now reading from props rather than state.
|
||||
var comments = this.props.comments;
|
||||
return (
|
||||
<div>
|
||||
{comments.map(function(comment) {
|
||||
return <Comment comment={comment} key={comment.id} />
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
// This is a parent component.
|
||||
// It subscribes to the data source and renders <CommentList />.
|
||||
var CommentListWithSubscription = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
comments: DataSource.getComments()
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
DataSource.addChangeListener(this.handleChange);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
DataSource.removeChangeListener(this.handleChange);
|
||||
},
|
||||
|
||||
handleChange: function() {
|
||||
this.setState({
|
||||
comments: DataSource.getComments()
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// We pass the current state as props to CommentList.
|
||||
return <CommentList comments={this.state.comments} />;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = CommentListWithSubscription;
|
||||
```
|
||||
|
||||
There is just one final step left to do.
|
||||
|
||||
Remember how we made `withLogging()` take a function and return another function wrapping it? We can apply a similar pattern to React components.
|
||||
|
||||
We will write a new function called `withSubscription(WrappedComponent)`. Its argument could be any React component. We will pass `CommentList` as `WrappedComponent`, but we could also apply `withSubscription()` to any other component in our codebase.
|
||||
|
||||
This function would return another component. The returned component would manage the subscription and render `<WrappedComponent />` with the current data.
|
||||
|
||||
We call this pattern a “higher-order component”.
|
||||
|
||||
The composition happens at React rendering level rather than with a direct function call. This is why it doesn’t matter whether the wrapped component is defined with `createClass()`, as an ES6 class or a function. If `WrappedComponent` is a React component, the component created by `withSubscription()` can render it.
|
||||
|
||||
```js
|
||||
// This function takes a component...
|
||||
function withSubscription(WrappedComponent) {
|
||||
// ...and returns another component...
|
||||
return React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
comments: DataSource.getComments()
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
// ... that takes care of the subscription...
|
||||
DataSource.addChangeListener(this.handleChange);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
DataSource.removeChangeListener(this.handleChange);
|
||||
},
|
||||
|
||||
handleChange: function() {
|
||||
this.setState({
|
||||
comments: DataSource.getComments()
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// ... and renders the wrapped component with the fresh data!
|
||||
return <WrappedComponent comments={this.state.comments} />;
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Now we can declare `CommentListWithSubscription` by applying `withSubscription` to `CommentList`:
|
||||
|
||||
```js
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
var comments = this.props.comments;
|
||||
return (
|
||||
<div>
|
||||
{comments.map(function(comment) {
|
||||
return <Comment comment={comment} key={comment.id} />
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
// withSubscription() returns a new component that
|
||||
// is subscribed to the data source and renders
|
||||
// <CommentList /> with up-to-date data.
|
||||
var CommentListWithSubscription = withSubscription(CommentList);
|
||||
|
||||
// The rest of the app is interested in the subscribed component
|
||||
// so we export it instead of the original unwrapped CommentList.
|
||||
module.exports = CommentListWithSubscription;
|
||||
```
|
||||
|
||||
#### Solution, Revisited
|
||||
|
||||
Now that we understand higher-order components better, let’s take another look at the complete solution that doesn’t involve mixins. There are a few minor changes that are annotated with inline comments:
|
||||
|
||||
```js
|
||||
function withSubscription(WrappedComponent) {
|
||||
return React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
comments: DataSource.getComments()
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
DataSource.addChangeListener(this.handleChange);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
DataSource.removeChangeListener(this.handleChange);
|
||||
},
|
||||
|
||||
handleChange: function() {
|
||||
this.setState({
|
||||
comments: DataSource.getComments()
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// Use JSX spread syntax to pass all props and state down automatically.
|
||||
return <WrappedComponent {...this.props} {...this.state} />;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Optional change: convert CommentList to a functional component
|
||||
// because it doesn't use lifecycle hooks or state.
|
||||
function CommentList(props) {
|
||||
var comments = props.comments;
|
||||
return (
|
||||
<div>
|
||||
{comments.map(function(comment) {
|
||||
return <Comment comment={comment} key={comment.id} />
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Instead of declaring CommentListWithSubscription,
|
||||
// we export the wrapped component right away.
|
||||
module.exports = withSubscription(CommentList);
|
||||
```
|
||||
|
||||
Higher-order components are a powerful pattern. You can pass additional arguments to them if you want to further customize their behavior. After all, they are not even a feature of React. They are just functions that receive components and return components that wrap them.
|
||||
|
||||
Like any solution, higher-order components have their own pitfalls. For example, if you heavily use [refs](/react/docs/more-about-refs.html), you might notice that wrapping something into a higher-order component changes the ref to point to the wrapping component. In practice we discourage using refs for component communication so we don’t think it’s a big issue. In the future, we might consider adding [ref forwarding](https://github.com/facebook/react/issues/4213) to React to solve this annoyance.
|
||||
|
||||
### Rendering Logic
|
||||
|
||||
The next most common use case for mixins that we discovered in our codebase is sharing rendering logic between components.
|
||||
|
||||
Here is a typical example of this pattern:
|
||||
|
||||
```js
|
||||
var RowMixin = {
|
||||
// Called by components from render()
|
||||
renderHeader: function() {
|
||||
return (
|
||||
<div className='row-header'>
|
||||
<h1>
|
||||
{this.getHeaderText() /* Defined by components */}
|
||||
</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
var UserRow = React.createClass({
|
||||
mixins: [RowMixin],
|
||||
|
||||
// Called by RowMixin.renderHeader()
|
||||
getHeaderText: function() {
|
||||
return this.props.user.fullName;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.renderHeader() /* Defined by RowMixin */}
|
||||
<h2>{this.props.user.biography}</h2>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Multiple components may be sharing `RowMixin` to render the header, and each of them would need to define `getHeaderText()`.
|
||||
|
||||
#### Solution
|
||||
|
||||
If you see rendering logic inside a mixin, it’s time to extract a component!
|
||||
|
||||
Instead of `RowMixin`, we will define a `<Row>` component. We will also replace the convention of defining a `getHeaderText()` method with the standard mechanism of top-data flow in React: passing props.
|
||||
|
||||
Finally, since neither of those components currently need lifecycle hooks or state, we can declare them as simple functions:
|
||||
|
||||
```js
|
||||
function RowHeader(props) {
|
||||
return (
|
||||
<div className='row-header'>
|
||||
<h1>{props.text}</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function UserRow(props) {
|
||||
return (
|
||||
<div>
|
||||
<RowHeader text={props.user.fullName} />
|
||||
<h2>{props.user.biography}</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Props keep component dependencies explicit, easy to replace, and enforceable with tools like [Flow](https://flowtype.org/) and [TypeScript](https://www.typescriptlang.org/).
|
||||
|
||||
> **Note:**
|
||||
>
|
||||
> Defining components as functions is not required. There is also nothing wrong with using lifecycle hooks and state—they are first-class React features. We use functional components in this example because they are easier to read and we didn’t need those extra features, but classes would work just as fine.
|
||||
|
||||
### Context
|
||||
|
||||
Another group of mixins we discovered were helpers for providing and consuming [React context](/react/docs/context.html). Context is an experimental unstable feature, has [certain issues](https://github.com/facebook/react/issues/2517), and will likely change its API in the future. We don’t recommend using it unless you’re confident there is no other way of solving your problem.
|
||||
|
||||
Nevertheless, if you already use context today, you might have been hiding its usage with mixins like this:
|
||||
|
||||
```js
|
||||
var RouterMixin = {
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
// The mixin provides a method so that components
|
||||
// don't have to use the context API directly.
|
||||
push: function(path) {
|
||||
this.context.router.push(path)
|
||||
}
|
||||
};
|
||||
|
||||
var Link = React.createClass({
|
||||
mixins: [RouterMixin],
|
||||
|
||||
handleClick: function(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
// This method is defined in RouterMixin.
|
||||
this.push(this.props.to);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<a onClick={this.handleClick}>
|
||||
{this.props.children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Link;
|
||||
```
|
||||
|
||||
#### Solution
|
||||
|
||||
We agree that hiding context usage from consuming components is a good idea until the context API stabilizes. However, we recommend using higher-order components instead of mixins for this.
|
||||
|
||||
Let the wrapping component grab something from the context, and pass it down with props to the wrapped component:
|
||||
|
||||
```js
|
||||
function withRouter(WrappedComponent) {
|
||||
return React.createClass({
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// The wrapper component reads something from the context
|
||||
// and passes it down as a prop to the wrapped component.
|
||||
var router = this.context.router;
|
||||
return <WrappedComponent {...this.props} router={router} />;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var Link = React.createClass({
|
||||
handleClick: function(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
// The wrapped component uses props instead of context.
|
||||
this.props.router.push(this.props.to);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<a onClick={this.handleClick}>
|
||||
{this.props.children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Don't forget to wrap the component!
|
||||
module.exports = withRouter(Link);
|
||||
```
|
||||
|
||||
If you’re using a third party library that only provides a mixin, we encourage you to file an issue with them linking to this post so that they can provide a higher-order component instead. In the meantime, you can create a higher-order component around it yourself in exactly the same way.
|
||||
|
||||
### Utility Methods
|
||||
|
||||
Sometimes, mixins are used solely to share utility functions between components:
|
||||
|
||||
```js
|
||||
var ColorMixin = {
|
||||
getLuminance(color) {
|
||||
var c = parseInt(color, 16);
|
||||
var r = (c & 0xFF0000) >> 16;
|
||||
var g = (c & 0x00FF00) >> 8;
|
||||
var b = (c & 0x0000FF);
|
||||
return (0.299 * r + 0.587 * g + 0.114 * b);
|
||||
}
|
||||
};
|
||||
|
||||
var Button = React.createClass({
|
||||
mixins: [ColorMixin],
|
||||
|
||||
render: function() {
|
||||
var theme = this.getLuminance(this.props.color) > 160 ? 'dark' : 'light';
|
||||
return (
|
||||
<div className={theme}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### Solution
|
||||
|
||||
Put utility functions into regular JavaScript modules and import them. This also makes it easier to test them or use them outside of your components:
|
||||
|
||||
```js
|
||||
var getLuminance = require('../utils/getLuminance');
|
||||
|
||||
var Button = React.createClass({
|
||||
render: function() {
|
||||
var theme = getLuminance(this.props.color) > 160 ? 'dark' : 'light';
|
||||
return (
|
||||
<div className={theme}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Other Use Cases
|
||||
|
||||
Sometimes people use mixins to selectively add logging to lifecycle hooks in some components. In the future, we intend to provide an [official DevTools API](https://github.com/facebook/react/issues/5306) that would let you implement something similar without touching the components. However it’s still very much a work in progress. If you heavily depend on logging mixins for debugging, you might want to keep using those mixins for a little longer.
|
||||
|
||||
If you can’t accomplish something with a component, a higher-order component, or a utility module, it could be mean that React should provide this out of the box. [File an issue](https://github.com/facebook/react/issues/new) to tell us about your use case for mixins, and we’ll help you consider alternatives or perhaps implement your feature request.
|
||||
|
||||
Mixins are not deprecated in the traditional sense. You can keep using them with `React.createClass()`, as we won’t be changing it further. Eventually, as ES6 classes gain more adoption and their usability problems in React are solved, we might split `React.createClass()` into a separate package because most people wouldn’t need it. Even in that case, your old mixins would keep working.
|
||||
|
||||
We believe that the alternatives above are better for the vast majority of cases, and we invite you to try writing React apps without using mixins.
|
||||
165
docs/_posts/2016-07-22-create-apps-with-no-configuration.md
Normal file
165
docs/_posts/2016-07-22-create-apps-with-no-configuration.md
Normal file
@@ -0,0 +1,165 @@
|
||||
---
|
||||
title: "Create Apps with No Configuration"
|
||||
author: gaearon
|
||||
---
|
||||
|
||||
**[Create React App](https://github.com/facebookincubator/create-react-app)** is a new officially supported way to create single-page React applications. It offers a modern build setup with no configuration.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
First, install the global package:
|
||||
|
||||
```sh
|
||||
npm install -g create-react-app
|
||||
```
|
||||
|
||||
Node.js 4.x or higher is required.
|
||||
|
||||
### Creating an App
|
||||
|
||||
Now you can use it to create a new app:
|
||||
|
||||
```sh
|
||||
create-react-app hello-world
|
||||
```
|
||||
|
||||
This will take a while as npm installs the transitive dependencies, but once it’s done, you will see a list of commands you can run in the created folder:
|
||||
|
||||

|
||||
|
||||
### Starting the Server
|
||||
|
||||
Run `npm start` to launch the development server. The browser will open automatically with the created app’s URL.
|
||||
|
||||

|
||||
|
||||
Create React App uses both Webpack and Babel under the hood.
|
||||
The console output is tuned to be minimal to help you focus on the problems:
|
||||
|
||||

|
||||
|
||||
ESLint is also integrated so lint warnings are displayed right in the console:
|
||||
|
||||

|
||||
|
||||
We only picked a small subset of lint rules that often lead to bugs.
|
||||
|
||||
### Building for Production
|
||||
|
||||
To build an optimized bundle, run `npm run build`:
|
||||
|
||||

|
||||
|
||||
It is minified, correctly envified, and the assets include content hashes for caching.
|
||||
|
||||
### One Dependency
|
||||
|
||||
Your `package.json` contains only a single build dependency and a few scripts:
|
||||
|
||||
```js
|
||||
{
|
||||
"name": "hello-world",
|
||||
"dependencies": {
|
||||
"react": "^15.2.1",
|
||||
"react-dom": "^15.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-scripts": "0.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"eject": "react-scripts eject"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We take care of updating Babel, ESLint, and Webpack to stable compatible versions so you can update a single dependency to get them all.
|
||||
|
||||
### Zero Configuration
|
||||
|
||||
It is worth repeating: there are no configuration files or complicated folder structures. The tool only generates the files you need to build your app.
|
||||
|
||||
```
|
||||
hello-world/
|
||||
README.md
|
||||
index.html
|
||||
favicon.ico
|
||||
node_modules/
|
||||
package.json
|
||||
src/
|
||||
App.css
|
||||
App.js
|
||||
index.css
|
||||
index.js
|
||||
logo.svg
|
||||
```
|
||||
|
||||
All the build settings are preconfigured and can’t be changed. Some features, such as testing, are currently missing. This is an intentional limitation, and we recognize it might not work for everybody. And this brings us to the last point.
|
||||
|
||||
### No Lock-In
|
||||
|
||||
We first saw this feature in [Enclave](https://github.com/eanplatter/enclave), and we loved it. We talked to [Ean](https://twitter.com/EanPlatter), and he was excited to collaborate with us. He already sent a few pull requests!
|
||||
|
||||
“Ejecting” lets you leave the comfort of Create React App setup at any time. You run a single command, and all the build dependencies, configs, and scripts are moved right into your project. At this point you can customize everything you want, but effectively you are forking our configuration and going your own way. If you’re experienced with build tooling and prefer to fine-tune everything to your taste, this lets you use Create React App as a boilerplate generator.
|
||||
|
||||
We expect that at early stages, many people will “eject” for one reason or another, but as we learn from them, we will make the default setup more and more compelling while still providing no configuration.
|
||||
|
||||
## Try It Out!
|
||||
|
||||
You can find [**Create React App**](https://github.com/facebookincubator/create-react-app) with additional instructions on GitHub.
|
||||
|
||||
This is an experiment, and only time will tell if it becomes a popular way of creating and building React apps, or fades into obscurity.
|
||||
|
||||
We welcome you to participate in this experiment. Help us build the React tooling that more people can use. We are always [open to feedback](https://github.com/facebookincubator/create-react-app/issues/11).
|
||||
|
||||
## The Backstory
|
||||
|
||||
React was one of the first libraries to embrace transpiling JavaScript. As a result, even though you can [learn React without any tooling](https://github.com/facebook/react/blob/3fd582643ef3d222a00a0c756292c15b88f9f83c/examples/basic-jsx/index.html), the React ecosystem has commonly become associated with an overwhelming explosion of tools.
|
||||
|
||||
Eric Clemmons called this phenomenon the “[JavaScript Fatigue](https://medium.com/@ericclemmons/javascript-fatigue-48d4011b6fc4)”:
|
||||
|
||||
>Ultimately, the problem is that by choosing React (and inherently JSX), you’ve unwittingly opted into a confusing nest of build tools, boilerplate, linters, & time-sinks to deal with before you ever get to create anything.
|
||||
|
||||
It is tempting to write code in ES2015 and JSX. It is sensible to use a bundler to keep the codebase modular, and a linter to catch the common mistakes. It is nice to have a development server with fast rebuilds, and a command to produce optimized bundles for production.
|
||||
|
||||
Combining these tools requires some experience with each of them. Even so, it is far too easy to get dragged into fighting small incompatibilities, unsatisfied peerDependencies, and illegible configuration files.
|
||||
|
||||
Many of those tools are plugin platforms and don’t directly acknowledge each other’s existence. They leave it up to the users to wire them together. The tools mature and change independently, and tutorials quickly get out of date.
|
||||
|
||||
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Marc was almost ready to implement his "hello world" React app <a href="https://t.co/ptdg4yteF1">pic.twitter.com/ptdg4yteF1</a></p>— Thomas Fuchs (@thomasfuchs) <a href="https://twitter.com/thomasfuchs/status/708675139253174273">March 12, 2016</a></blockquote>
|
||||
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||
|
||||
This doesn’t mean those tools aren’t great. To many of us, they have become indispensable, and we very much appreciate the effort of their maintainers. They already have too much on their plates to worry about the state of the React ecosystem.
|
||||
|
||||
Still, we knew it was frustrating to spend days setting up a project when all you wanted was to learn React. We wanted to fix this.
|
||||
|
||||
## Could We Fix This?
|
||||
|
||||
We found ourselves in an unusual dilemma.
|
||||
|
||||
So far, [our strategy](/react/contributing/design-principles.html#dogfooding) has been to only release the code that we are using at Facebook. This helped us ensure that every project is battle-tested and has clearly defined scope and priorities.
|
||||
|
||||
However, tooling at Facebook is different than at many smaller companies. Linting, transpilation, and packaging are all handled by powerful remote development servers, and product engineers don’t need to configure them. While we wish we could give a dedicated server to every user of React, even Facebook cannot scale that well!
|
||||
|
||||
The React community is very important to us. We knew that we couldn’t fix the problem within the limits of our open source philosophy. This is why we decided to make an exception, and to ship something that we didn’t use ourselves, but that we thought would be useful to the community.
|
||||
|
||||
## The Quest for a React <abbr title="Command Line Interface">CLI</abbr>
|
||||
|
||||
Having just attended [EmberCamp](http://embercamp.com/) a week ago, I was excited about [Ember CLI](https://ember-cli.com/). Ember users have a great “getting started” experience thanks to a curated set of tools united under a single command-line interface. I have heard similar feedback about [Elm Reactor](https://github.com/elm-lang/elm-reactor).
|
||||
|
||||
Providing a cohesive curated experience is valuable by itself, even if the user could in theory assemble those parts themselves. Kathy Sierra [explains it best](http://seriouspony.com/blog/2013/7/24/your-app-makes-me-fat):
|
||||
|
||||
>If your UX asks the user to make *choices*, for example, even if those choices are both clear and useful, the act of *deciding* is a cognitive drain. And not just *while* they’re deciding... even *after* we choose, an unconscious cognitive background thread is slowly consuming/leaking resources, “Was *that* the right choice?”
|
||||
|
||||
I never tried to write a command-line tool for React apps, and neither has [Christopher](https://twitter.com/vjeux). We were chatting on Messenger about this idea, and we decided to work together on it for a week as a hackathon project.
|
||||
|
||||
We knew that such projects traditionally haven’t been very successful in the React ecosystem. Christopher told me that multiple “React CLI” projects have started and failed at Facebook. The community tools with similar goals also exist, but so far they have not yet gained enough traction.
|
||||
|
||||
Still, we decided it was worth another shot. Christopher and I created a very rough proof of concept on the weekend, and [Kevin](https://twitter.com/lacker) soon joined us.
|
||||
|
||||
We invited some of the community members to collaborate with us, and we have spent this week working on this tool. We hope that you’ll enjoy using it! [Let us know what you think.](https://github.com/facebookincubator/create-react-app/issues/11)
|
||||
|
||||
We would like to express our gratitude to [Max Stoiber](https://twitter.com/mxstbr), [Jonny Buchanan](https://twitter.com/jbscript), [Ean Platter](https://twitter.com/eanplatter), [Tyler McGinnis](https://github.com/tylermcginnis), [Kent C. Dodds](https://github.com/kentcdodds), and [Eric Clemmons](https://twitter.com/ericclemmons) for their early feedback, ideas, and contributions.
|
||||
81
docs/_posts/2016-08-05-relay-state-of-the-state.md
Normal file
81
docs/_posts/2016-08-05-relay-state-of-the-state.md
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: "Relay: State of the State"
|
||||
author: josephsavona
|
||||
---
|
||||
|
||||
This month marks a year since we released Relay and we'd like to share an update on the project and what's next.
|
||||
|
||||
## A Year In Review
|
||||
|
||||
A year after launch, we're incredibly excited to see an active community forming around Relay and that companies such as Twitter are [using Relay in production](https://fabric.io/blog/building-fabric-mission-control-with-graphql-and-relay):
|
||||
|
||||
> For a project like mission control, GraphQL and Relay were a near-perfect solution, and the cost of building it any other way justified the investment.
|
||||
>
|
||||
> -- <cite>Fin Hopkins</cite>
|
||||
|
||||
This kind of positive feedback is really encouraging (I'll admit to re-reading that post far too many times), and great motivation for us to keep going and make Relay even better.
|
||||
|
||||
With the community's help we've already come a long way since the technical preview. Here are some highlights:
|
||||
|
||||
- In March we added support for server-side rendering and for creating multiple instances of Relay on a single page. This was a coordinated effort over the course of several months by community members [Denis Nedelyaev](https://github.com/denvned) and [Gerald Monaco](https://github.com/devknoll) (now at Facebook).
|
||||
- Also in March we added support for React Native. While we use Relay and React Native together internally, they didn't quite work together in open-source out of the box. We owe a big thanks to [Adam Miskiewicz](https://github.com/skevy), [Tom Burns](https://github.com/boourns), [Gaëtan Renaudeau](https://github.com/gre), [David Aurelio](https://github.com/davidaurelio), [Martín Bigio](https://github.com/martinbigio), [Paul O’Shannessy](https://github.com/zpao), [Ben Alpert](https://github.com/spicyj), and many others who helped track down and resolve issues. Finally, thanks to [Steven Luscher](https://github.com/steveluscher) for coordinating this effort and building the first Relay/ReactNative example app.
|
||||
|
||||
We've also seen some great open-source projects spring up around Relay:
|
||||
|
||||
- [Denis Nedelyaev](https://github.com/denvned) created [isomorphic-relay](https://github.com/denvned/isomorphic-relay/), a package that helps developers build server-rendered Relay apps where data is prepared on the server and then used to bootstrap the app on the client.
|
||||
- [Jimmy Jia](https://github.com/taion) created [react-router-relay](https://github.com/relay-tools/react-router-relay) to integrate Relay data-fetching into React Router.
|
||||
- [Pavel Chertorogov](https://github.com/nodkz) released [relay-network-layer](https://github.com/nodkz/react-relay-network-layer), which adds features such as batching query requests, middleware, authentication, logging, and more.
|
||||
|
||||
This is just a small sampling of the community's contributions. So far we've merged over 300 PRs - about 25% of our commits - from over 80 of you. These PRs have improved everything from the website and docs down the very core of the framework. We're humbled by these outstanding contributions and excited to keep working with each of you!
|
||||
|
||||
# Retrospective & Roadmap
|
||||
|
||||
Earlier this year we paused to reflect on the state of the project. What was working well? What could be improved? What features should we add, and what could we remove? A few themes emerged: performance on mobile, developer experience, and empowering the community.
|
||||
|
||||
## Mobile Perf
|
||||
|
||||
First, Relay was built to serve the needs of product developers at Facebook. In 2016, that means helping developers to build apps that work well on [mobile devices connecting on slower networks](https://newsroom.fb.com/news/2015/10/news-feed-fyi-building-for-all-connectivity/). For example, people in developing markets commonly use [2011 year-class phones](https://code.facebook.com/posts/307478339448736/year-class-a-classification-system-for-android/) and connect via [2G class networks](https://code.facebook.com/posts/952628711437136/classes-performance-and-network-segmentation-on-android/). These scenarios present their own challenges.
|
||||
|
||||
Therefore, one of our primary goals this year is to optimize Relay for performance on low-end mobile devices *first*, knowing that this can translate to improved performance on high-end devices as well. In addition to standard approaches such as benchmarking, profiling, and optimizations, we're also working on big-picture changes.
|
||||
|
||||
For example, in today's Relay, here's what happens when an app is opened. First, React Native starts initializing the JavaScript context (loading and parsing your code and then running it). When this finishes, the app executes and Relay sees that you need data. It constructs and prints the query, uploads the query text to the server, processes the response, and renders your app. (Note that this process applies on the web, except that the code has to be *downloaded* instead of loaded from the device.)
|
||||
|
||||
Ideally, though, we could begin fetching data as soon as the native code had loaded - in parallel with the JS context initialization. By the time your JS code was ready to run, the data-fetching would already be under way. To do this we would need a way to determine *statically* - at build time - what query an application would send.
|
||||
|
||||
The key is that GraphQL is already static - we just need to fully embrace this fact. More on this later.
|
||||
|
||||
## Developer Experience
|
||||
|
||||
Next, we've paid attention to the community's feedback and know that, to put it simply, Relay could be "easier" to use (and "simpler" too). This isn't entirely surprising to us - Relay was originally designed as a routing library and gradually morphed into a data-fetching library. Concepts like Relay "routes", for example, no longer serve as critical a role and are just one more concept that developers have to learn about. Another example is mutations: while writes *are* inherently more complex than reads, our API doesn't make the simple things simple enough.
|
||||
|
||||
Alongside our focus on mobile performance, we've also kept the developer experience in mind as we evolve Relay core.
|
||||
|
||||
## Empowering the Community
|
||||
|
||||
Finally, we want to make it easier for people in the community to develop useful libraries that work with Relay. By comparison, React's small surface area - components - allows developers to build cool things like routing, higher-order components, or reusable text editors. For Relay, this would mean having the framework provide core primitives that users can build upon. We want it to be possible for the community to integrate Relay with view libraries other than React, or to build real-time subscriptions as a complementary library.
|
||||
|
||||
# What's Next
|
||||
|
||||
These were big goals, and also a bit scary; we knew that incremental improvements would only allow us to move so fast. So in April we started a project to build a new implementation of Relay core targeting low-end mobile devices from the start.
|
||||
|
||||
As you can guess since we're writing this, the experiment was a success. The result is a new core that retains the best parts of Relay today - colocated components & data-dependencies, automatic data/view consistency, declarative data-fetching - while improving performance on mobile devices and addressing several common areas of confusion.
|
||||
|
||||
We're currently focused on shipping the first applications using the new core: ironing out bugs, refining the API changes and developer experience, and adding any missing features. We're excited to bring these changes to open source, and will do so once we've proven them in production. We'll go into more detail in some upcoming talks - links below - but for now here's an overview:
|
||||
|
||||
- **Static Queries**: By adding a couple of Relay-specific directives, we've been able to retain the expressivity of current Relay queries using static syntax (concretely: you know what query an app will execute just by looking at the source text, without having to run that code). For starters this will allow Relay apps to start fetching data in parallel with JavaScript initialization. But it also unlocks other possibilities: knowing the query ahead of time means that we can generate optimized code for handling query responses, for example, or for reading query data from an offline cache.
|
||||
- **Expressive Mutations**: We'll continue to support a higher-level mutation API for common cases, but will also provide a lower-level API that allows "raw" data access where necessary. If you need to order a list of cached elements, for example, there will be a way to `sort()` it.
|
||||
- **Route-less Relay**: Routes will be gone in open source. Instead of a route with multiple query definitions, you'll just provide a single query with as many root fields as you want.
|
||||
- **Cache Eviction/Garbage Collection**: The API and architecture is designed from the start to allow removing cached data that is no longer referenced by a mounted view.
|
||||
|
||||
Stepping back, we recognize that any API changes will require an investment on your part. To make the transition easier, though, *we will continue to support the current API for the foreseeable future* (we're still using it too). And as much as possible we will open-source the tools that we use to migrate our own code. Ideas that we're exploring include codemods, an interoperability layer for the old/new APIs, and tutorials & guides to ease migration.
|
||||
|
||||
Ultimately, we're making these changes because we believe they make Relay better all around: simpler for developers building apps and faster for the people using them.
|
||||
|
||||
# Conclusion
|
||||
|
||||
If you made it this far, congrats and thanks for reading! We'll be sharing more information about these changes in some upcoming talks:
|
||||
|
||||
- [Greg Hurrell](https://github.com/wincent) will presenting a Relay "Deep Dive" at the [Silicon Valley ReactJS Meetup](http://www.meetup.com/Silicon-Valley-ReactJS-Meetup/events/232236845/) on August 17th.
|
||||
- I ([@josephsavona](https://github.com/josephsavona)) will be speaking about Relay at [React Rally](http://www.reactrally.com) on August 25th.
|
||||
|
||||
We can't wait to share the new code with you and are working as fast as we can to do so!
|
||||
230
docs/_posts/2016-09-28-our-first-50000-stars.md
Normal file
230
docs/_posts/2016-09-28-our-first-50000-stars.md
Normal file
@@ -0,0 +1,230 @@
|
||||
---
|
||||
title: "Our First 50,000 Stars"
|
||||
author: vjeux
|
||||
---
|
||||
|
||||
Just three and a half years ago we open sourced a little JavaScript library called React. The journey since that day has been incredibly exciting.
|
||||
|
||||
## Commemorative T-Shirt
|
||||
|
||||
In order to celebrate 50,000 GitHub stars, [Maggie Appleton](http://www.maggieappleton.com/) from [egghead.io](http://egghead.io/) has designed us a special T-shirt, which will be available for purchase from Teespring **only for a week** through Thursday, October 6. Maggie also wrote [a blog post](https://www.behance.net/gallery/43269677/Reacts-50000-Stars-Shirt) showing all the different concepts she came up with before settling on the final design.
|
||||
|
||||
<a target="_blank" href="https://teespring.com/react-50000-stars"><img src="/react/img/blog/react-50k-tshirt.jpg" width="650" height="340" alt="React 50k Tshirt" /></a>
|
||||
|
||||
The T-shirts are super soft using American Apparel's tri-blend fabric; we also have kids and toddler T-shirts and baby onesies available.
|
||||
|
||||
* [Adult T-shirts (straight-cut and fitted)](https://teespring.com/react-50000-stars)
|
||||
* [Kids T-shirts](https://teespring.com/react-50000-stars-kids)
|
||||
* [Toddler T-Shirts](https://teespring.com/react-50000-stars-toddler)
|
||||
* [Baby Onesies](https://teespring.com/react-50000-stars-baby)
|
||||
|
||||
Proceeds from the shirts will be donated to [CODE2040](http://www.code2040.org/), a nonprofit that creates access, awareness, and opportunities in technology for underrepresented minorities with a specific focus on Black and Latinx talent.
|
||||
|
||||
## Archeology
|
||||
|
||||
We've spent a lot of time trying to explain the concepts behind React and the problems it attempts to solve, but we haven't talked much about how React evolved before being open sourced. This milestone seemed like as good a time as any to dig through the earliest commits and share some of the more important moments and fun facts.
|
||||
|
||||
The story begins in our ads org, where we were building incredibly sophisticated client side web apps using an internal MVC framework called [BoltJS](http://web.archive.org/web/20130608154901/http://shaneosullivan.github.io/boltjs/intro.html). Here's a sample of what some Bolt code looked like:
|
||||
|
||||
```js
|
||||
var CarView = require('javelin/core').createClass({
|
||||
name: 'CarView',
|
||||
extend: require('container').Container,
|
||||
properties: {
|
||||
wheels: 4,
|
||||
},
|
||||
declare: function() {
|
||||
return {
|
||||
childViews: [
|
||||
{ content: 'I have ' },
|
||||
{ ref: 'wheelView' },
|
||||
{ content: ' wheels' }
|
||||
]
|
||||
};
|
||||
},
|
||||
setWheels: function(wheels) {
|
||||
this.findRef('wheelView').setContent(wheels);
|
||||
},
|
||||
getWheels: function() {
|
||||
return this.findRef('wheelView').getContent();
|
||||
},
|
||||
});
|
||||
|
||||
var car = new CarView();
|
||||
car.setWheels(3);
|
||||
car.placeIn(document.body);
|
||||
//<div>
|
||||
// <div>I have </div>
|
||||
// <div>3</div>
|
||||
// <div> wheels</div>
|
||||
//</div>
|
||||
```
|
||||
|
||||
Bolt introduced a number of APIs and features that would eventually make their way into React including `render`, `createClass`, and `refs`. Bolt introduced the concept of `refs` as a way to create references to nodes that can be used imperatively. This was relevant for legacy interoperability and incremental adoption, and while React would eventually strive to be a lot more functional, `refs` proved to be a very useful way to break out of the functional paradigm when the need arose.
|
||||
|
||||
But as our applications grew more and more sophisticated, our Bolt codebases got pretty complicated. Recognizing some of the framework's shortcomings, [Jordan Walke](https://twitter.com/jordwalke) started experimenting with a side-project called [FaxJS](https://github.com/jordwalke/FaxJs). His goal was to solve many of the same problems as Bolt, but in a very different way. This is actually where most of React's fundamentals were born, including props, state, re-evaluating large portions of the tree to “diff” the UI, server-side rendering, and a basic concept of components.
|
||||
|
||||
```js
|
||||
TestProject.PersonDisplayer = {
|
||||
structure : function() {
|
||||
return Div({
|
||||
classSet: { personDisplayerContainer: true },
|
||||
titleDiv: Div({
|
||||
classSet: { personNameTitle: true },
|
||||
content: this.props.name
|
||||
}),
|
||||
nestedAgeDiv: Div({
|
||||
content: 'Interests: ' + this.props.interests
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## FBolt is Born
|
||||
|
||||
Through his FaxJS experiment, Jordan became convinced that functional APIs — which discouraged mutation — offered a better, more scalable way to build user interfaces. He imported his library into Facebook's codebase in March of 2012 and renamed it “FBolt”, signifying an extension of Bolt where components are written in a functional programming style. Or maybe “FBolt” was a nod to FaxJS – he didn't tell us! ;)
|
||||
|
||||
The interoperability between FBolt and Bolt allowed us to experiment with replacing just one component at a time with more functional component APIs. We could test the waters of this new functional paradigm, without having to go all in. We started with the components that were clearly best expressed functionally and then we would later continue to push the boundaries of what we could express as functions.
|
||||
|
||||
Realizing that FBolt wouldn't be a great name for the library when used on its own, Jordan Walke and [Tom Occhino](https://twitter.com/tomocchino) decided on a new name: “React.” After Tom sent out the diff to rename everything to React, Jordan commented:
|
||||
|
||||
|
||||
> Jordan Walke:
|
||||
I might add for the sake of discussion, that many systems advertise some kind of reactivity, but they usually require that you set up some kind of point-to-point listeners and won't work on structured data. This API reacts to any state or property changes, and works with data of any form (as deeply structured as the graph itself) so I think the name is fitting.
|
||||
|
||||
|
||||
Most of Tom's other commits at the time were on the first version of [GraphiQL](https://github.com/graphql/graphiql), a project which was recently open sourced.
|
||||
|
||||
## Adding JSX
|
||||
|
||||
Since about 2010 Facebook has been using an extension of PHP called [XHP](https://www.facebook.com/notes/facebook-engineering/xhp-a-new-way-to-write-php/294003943919/), which enables engineers to create UIs using XML literals right inside their PHP code. It was first introduced to help prevent XSS holes but ended up being an excellent way to structure applications with custom components.
|
||||
|
||||
```js
|
||||
final class :a:post extends :x:element {
|
||||
attribute :a;
|
||||
protected function render(): XHPRoot {
|
||||
$anchor = <a>{$this->getChildren()}</a>;
|
||||
$form = (
|
||||
<form
|
||||
method="post"
|
||||
action={$this->:href}
|
||||
target={$this->:target}
|
||||
class="postLink"
|
||||
>{$anchor}</form>
|
||||
);
|
||||
$this->transferAllAttributes($anchor);
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Before Jordan's work had even made its way into the Facebook codebase, Adam Hupp implemented an XHP-like concept for JavaScript, written in Haskell. This system enabled you to write the following inside a JavaScript file:
|
||||
|
||||
```js
|
||||
function :example:hello(attrib, children) {
|
||||
return (
|
||||
<div class="special">
|
||||
<h1>Hello, World!</h1>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
It would compile the above into the following normal ES3-compatible JavaScript:
|
||||
|
||||
```js
|
||||
function jsx_example_hello(attrib, children) {
|
||||
return (
|
||||
S.create("div", {"class": "special"}, [
|
||||
S.create("h1", {}, ["Hello, World!"]),
|
||||
children
|
||||
]
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
In this prototype, `S.create` would immediately create and return a DOM node. Most of the conversations on this prototype revolved around the performance characteristics of `innerHTML` versus creating DOM nodes directly. At the time, it would have been less than ideal to push developers universally in the direction of creating DOM nodes directly since it did not perform as well, especially in Firefox and IE. Facebook's then-CTO [Bret Taylor](https://twitter.com/btaylor) chimed in on the discussion at the time in favor of `innerHTML` over `document.createElement`:
|
||||
|
||||
|
||||
> Bret Taylor:
|
||||
If you are not convinced about innerHTML, here is a small microbenchmark. It is about the same in Chrome. innerHTML is about 30% faster in the latest version of Firefox (much more in previous versions), and about 90% faster in IE8.
|
||||
|
||||
|
||||
This work was eventually abandoned but was revived after React made its way into the codebase. Jordan sidelined the previous performance discussions by introducing the concept of a “Virtual DOM,” though its eventual name didn't exist yet.
|
||||
|
||||
|
||||
> Jordan Walke:
|
||||
> For the first step, I propose that we do the easiest, yet most general transformation possible. My suggestion is to simply map xml expressions to function call expressions.
|
||||
>
|
||||
> - `<x></x>` becomes `x( )`
|
||||
> - `<x height=12></x>` becomes `x( {height:12} )`
|
||||
> - `<x> <y> </y> </x>` becomes `x({ childList: [y( )] })`
|
||||
>
|
||||
> At this point, JSX doesn't need to know about React - it's just a convenient way to write function calls. Coincidentally, React's primary abstraction is the function. Okay maybe it's not so coincidental ;)
|
||||
|
||||
|
||||
Adam made a very insightful comment, which is now the default way we write lists in React with JSX.
|
||||
|
||||
|
||||
> Adam Hupp:
|
||||
> I think we should just treat arrays of elements as a frag. This is useful for constructs like:
|
||||
>
|
||||
> ```js
|
||||
<ul>{foo.map(function(i) { return <li>{i.data}</li>; })}</ul>
|
||||
```
|
||||
>
|
||||
> In this case the ul(..) will get a childList with a single child, which is itself a list.
|
||||
|
||||
|
||||
React didn't end up using Adam's implementation directly. Instead, we created JSX by forking [js-xml-literal](https://github.com/laverdet/js-xml-literal), a side project by XHP creator Marcel Laverdet. JSX took its name from js-xml-literal, which Jordan modified to just be syntactic sugar for deeply nested function calls.
|
||||
|
||||
## API Churn
|
||||
|
||||
During the first year of React, internal adoption was growing quickly but there was quite a lot of churn in the component APIs and naming conventions:
|
||||
|
||||
* `project` was renamed to `declare` then to `structure` and finally to `render`.
|
||||
* `Componentize` was renamed to `createComponent` and finally to `createClass`.
|
||||
|
||||
As the project was about to be open sourced, [Lee Byron](https://twitter.com/leeb) sat down with Jordan Walke, Tom Occhino and Sebastian Markbåge in order to refactor, reimplement, and rename one of React's most beloved features – the lifecycle API. Lee [came up with a well-designed API](https://gist.github.com/vjeux/f2b015d230cc1ab18ed1df30550495ed) that is still in place today.
|
||||
|
||||
* Concepts
|
||||
* component - a ReactComponent instance
|
||||
* state - internal state to a component
|
||||
* props - external state to a component
|
||||
* markup - the stringy HTML-ish stuff components generate
|
||||
* DOM - the document and elements within the document
|
||||
* Actions
|
||||
* mount - to put a component into a DOM
|
||||
* initialize - to prepare a component for rendering
|
||||
* update - a transition of state (and props) resulting a render.
|
||||
* render - a side-effect-free process to get the representation (markup) of a component.
|
||||
* validate - make assertions about something created and provided
|
||||
* destroy - opposite of initialize
|
||||
* Operands
|
||||
* create - make a new thing
|
||||
* get - get an existing thing
|
||||
* set - merge into existing
|
||||
* replace - replace existing
|
||||
* receive - respond to new data
|
||||
* force - skip checks to do action
|
||||
* Notifications
|
||||
* shouldObjectAction
|
||||
* objectWillAction
|
||||
* objectDidAction
|
||||
|
||||
## Instagram
|
||||
|
||||
In 2012, Instagram got acquired by Facebook. [Pete Hunt](https://twitter.com/floydophone), who was working on Facebook photos and videos at the time, joined their newly formed web team. He wanted to build their website completely in React, which was in stark contrast with the incremental adoption model that had been used at Facebook.
|
||||
|
||||
To make this happen, React had to be decoupled from Facebook's infrastructure, since Instagram didn't use any of it. This project acted as a forcing function to do the work needed to open source React. In the process, Pete also discovered and promoted a little project called Webpack. He also implemented the `renderToString` primitive which was needed to do server-side rendering.
|
||||
|
||||
As we started to prepare for the open source launch, [Maykel Loomans](https://twitter.com/miekd), a designer on Instagram, made a mock of what the website could look like. The header ended up defining the visual identity of React: its logo and the electric blue color!
|
||||
|
||||
<center><a target="_blank" href="/react/img/blog/react-50k-mock-full.jpg"><img src="/react/img/blog/react-50k-mock.jpg" width="400" height="410" alt="React website mock" /></a></center>
|
||||
|
||||
In its earliest days, React benefitted tremendously from feedback, ideas, and technical contributions of early adopters and collaborators all over the company. While it might look like an overnight success in hindsight, the story of React is actually a great example of how new ideas often need to go through several rounds of refinement, iteration, and course correction over a long period of time before reaching their full potential.
|
||||
|
||||
React's approach to building user interfaces with functional programming principles has changed the way we do things in just a few short years. It goes without saying, but React would be nothing without the amazing open source community that's built up around it!
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
id: acknowledgements
|
||||
title: Acknowledgements
|
||||
layout: single
|
||||
permalink: acknowledgements.html
|
||||
---
|
||||
|
||||
We'd like to thank all of our contributors:
|
||||
|
||||
262
docs/contributing/codebase-overview.md
Normal file
262
docs/contributing/codebase-overview.md
Normal file
@@ -0,0 +1,262 @@
|
||||
---
|
||||
id: codebase-overview
|
||||
title: Codebase Overview
|
||||
layout: contributing
|
||||
permalink: contributing/codebase-overview.html
|
||||
prev: how-to-contribute.html
|
||||
next: design-principles.html
|
||||
---
|
||||
|
||||
This section will give you an overview of the React codebase organization, its conventions, and the implementation.
|
||||
|
||||
If you want to [contribute to React](/react/contributing/how-to-contribute.html) we hope that this guide will help you feel more comfortable making changes.
|
||||
|
||||
We don't necessarily recommend any of these conventions in React apps. Many of them exist for historical reasons and might change with time.
|
||||
|
||||
### Custom Module System
|
||||
|
||||
At Facebook, internally we use a custom module system called "Haste". It is similar to [CommonJS](https://nodejs.org/docs/latest/api/modules.html) and also uses `require()` but has a few important differences that often confuse outside contributors.
|
||||
|
||||
In CommonJS, when you import a module, you need to specify its relative path:
|
||||
|
||||
```js
|
||||
// Importing from the same folder:
|
||||
var setInnerHTML = require('./setInnerHTML');
|
||||
|
||||
// Importing from a different folder:
|
||||
var setInnerHTML = require('../utils/setInnerHTML');
|
||||
|
||||
// Importing from a deeply nested folder:
|
||||
var setInnerHTML = require('../client/utils/setInnerHTML');
|
||||
```
|
||||
|
||||
However, with Haste **all filenames are globally unique.** In the React codebase, you can import any module from any other module by its name alone:
|
||||
|
||||
```js
|
||||
var setInnerHTML = require('setInnerHTML');
|
||||
```
|
||||
|
||||
Haste was originally developed for giant apps like Facebook. It's easy to move files to different folders and import them without worrying about relative paths. The fuzzy file search in any editor always takes you to the correct place thanks to globally unique names.
|
||||
|
||||
React itself was extracted from Facebook codebase and uses Haste for historical reasons. In the future, we will probably [migrate React to use CommonJS or ES Modules](https://github.com/facebook/react/issues/6336) to be more aligned with the community. However this requires changes in Facebook internal infrastructure so it is unlikely to happen very soon.
|
||||
|
||||
**Haste will make more sense to you if you remember a few rules:**
|
||||
|
||||
* All filenames in the React source code are unique. This is why they're sometimes verbose.
|
||||
* When you add a new file, make sure you include a [license header](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/client/utils/setInnerHTML.js#L1-L10). You can copy it from any existing file. A license header always includes [a line like this](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/client/utils/setInnerHTML.js#L9). Change it to match the name of the file you created.
|
||||
* Don’t use relative paths when importing. Instead of `require('./setInnerHTML')`, write `require('setInnerHTML')`.
|
||||
|
||||
When we compile React for npm, a script copies all the modules into [a single flat directory called `lib`](https://unpkg.com/react@15/lib/) and prepends all `require()` paths with `./`. This way Node, Browserify, Webpack, and other tools can understand React build output without being aware of Haste.
|
||||
|
||||
**If you're reading React source on GitHub and want to quickly jump to any file, press "t".**
|
||||
|
||||
This is a GitHub shortcut for searching the current repo for fuzzy filename matches. Start typing the name of the file you are looking for, and it will show up as the first match.
|
||||
|
||||
### External Dependencies
|
||||
|
||||
React has almost no external dependencies. Usually a `require()` points to a file in React's own codebase. However there are a few relatively rare exceptions.
|
||||
|
||||
If you see a `require()` that does not correspond to a file in the React repository, you can look in a special repository called [fbjs](https://github.com/facebook/fbjs). For example, `require('warning')` will resolve to the [`warning` module from fbjs](https://github.com/facebook/fbjs/blob/df9047fec0bbd1e64635ae369c045975777cba7c/packages/fbjs/src/__forks__/warning.js).
|
||||
|
||||
The [fbjs repository](https://github.com/facebook/fbjs) exists because React shares some small utilities with libraries like [Relay](https://github.com/facebook/relay), and we keep them in sync. We don't depend on equivalent small modules in the Node ecosystem because we want Facebook engineers to be able to make changes to them whenever necessary. None of the utilities inside fbjs are considered to be public API, and they are only intended for use by Facebook projects such as React.
|
||||
|
||||
### Top-Level Folders
|
||||
|
||||
After cloning the [React repository](https://github.com/facebook/react), you will see a few top-level folders in it:
|
||||
|
||||
* [`src`](https://github.com/facebook/react/tree/master/src) is the source code of React. **If your change is related to the code, `src` is where you'll spend most of your time.**
|
||||
* [`docs`](https://github.com/facebook/react/tree/master/docs) is the React documentation website. When you change APIs, make sure to update the relevant Markdown files.
|
||||
* [`examples`](https://github.com/facebook/react/tree/master/examples) contains a few small React demos with different build setups.
|
||||
* [`packages`](https://github.com/facebook/react/tree/master/packages) contains metadata (such as `package.json`) for all packages in the React repository. Nevertheless their source code is still located inside [`src`](https://github.com/facebook/react/tree/master/src).
|
||||
* `build` is the build output of React. It is not in the repository but it will appear in your React clone after you [build it](/react/contributing/how-to-contribute.html#development-workflow) for the first time.
|
||||
|
||||
There are a few other top-level folders but they are mostly used for the tooling and you likely won't ever encounter them when contributing.
|
||||
|
||||
### Colocated Tests
|
||||
|
||||
We don't have a top-level directory for unit tests. Instead, we put them into a directories called `__tests__` relative to the files that they test.
|
||||
|
||||
For example, a test for [`setInnerHTML.js`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/client/utils/setInnerHTML.js) is located in [`__tests__/setInnerHTML-test.js`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/client/utils/__tests__/setInnerHTML-test.js) right next to it.
|
||||
|
||||
### Warnings and Invariants
|
||||
|
||||
React codebase uses the `warning` module to display warnings:
|
||||
|
||||
```js
|
||||
var warning = require('warning');
|
||||
|
||||
warning(
|
||||
2 + 2 === 4,
|
||||
'Math is not working today.'
|
||||
);
|
||||
```
|
||||
|
||||
**The warning is shown when the `warning` condition is `false`.**
|
||||
|
||||
One way to think about it is that the condition should reflect the normal situation rather than the exceptional one.
|
||||
|
||||
It is a good idea to avoid spamming the console with duplicate warnings:
|
||||
|
||||
````js
|
||||
var warning = require('warning');
|
||||
|
||||
var didWarnAboutMath = false;
|
||||
if (!didWarnAboutMath) {
|
||||
warning(
|
||||
2 + 2 === 4,
|
||||
'Math is not working today.'
|
||||
);
|
||||
didWarnAboutMath = true;
|
||||
}
|
||||
```
|
||||
|
||||
Warnings are only enabled in development. In production, they are completely stripped out. If you need to forbid some code path from executing, use `invariant` module instead:
|
||||
|
||||
```js
|
||||
var invariant = require('invariant');
|
||||
|
||||
invariant(
|
||||
2 + 2 === 4,
|
||||
'You shall not pass!'
|
||||
);
|
||||
```
|
||||
|
||||
**The invariant is thrown when the `invariant` condition is `false`.**
|
||||
|
||||
"Invariant" is just a way of saying "this condition always holds true". You can think about it as making an assertion.
|
||||
|
||||
It is important to keep development and production behavior similar, so `invariant` throws both in development and in production. The error messages are automatically replaced with error codes in production to avoid negatively affecting the byte size.
|
||||
|
||||
### Development and Production
|
||||
|
||||
You can use `__DEV__` pseudo-global variable in the codebase to guard development-only blocks of code.
|
||||
|
||||
It is inlined during the compile step, and turns into `process.env.NODE_ENV !== 'production'` checks in the CommonJS builds.
|
||||
|
||||
For standalone builds, it becomes `true` in the unminified build, and gets completely stripped out with the `if` blocks it guards in the minified build.
|
||||
|
||||
```js
|
||||
if (__DEV__) {
|
||||
// This code will only run in development.
|
||||
}
|
||||
```
|
||||
|
||||
### Multiple Packages
|
||||
|
||||
React is a [monorepo](http://danluu.com/monorepo/). Its repository contains multiple separate packages so that their changes can be coordinated together, and documentation and issues live in one place.
|
||||
|
||||
The npm metadata such as `package.json` files is located in the [`packages`](https://github.com/facebook/react/tree/master/packages) top-level folder. However there is almost no real code in it.
|
||||
|
||||
For example, [`packages/react/react.js`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/packages/react/react.js) re-exports [`src/isomorphic/React.js`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/isomorphic/React.js), the real npm entry point. Other packages mostly repeat this pattern. All the important code lives in [`src`](https://github.com/facebook/react/tree/master/src).
|
||||
|
||||
While the code is separated in the source tree, the exact package boundaries are slightly different for npm packages and standalone browser builds.
|
||||
|
||||
### React Core
|
||||
|
||||
The "core" of React includes all the [top-level `React` APIs](/react/docs/top-level-api.html#react), for example:
|
||||
|
||||
* `React.createElement()`
|
||||
* `React.createClass()`
|
||||
* `React.Component`
|
||||
* `React.Children`
|
||||
* `React.PropTypes`
|
||||
|
||||
**React core only includes the APIs necessary to define components.** It does not include the [reconciliation](/react/docs/reconciliation.html) algorithm or any platform-specific code. It is used both by React DOM and React Native components.
|
||||
|
||||
The code for React core is located in [`src/isomorphic`](https://github.com/facebook/react/tree/master/src/isomorphic) in the source tree. It is available on npm as the [`react`](https://www.npmjs.com/package/react) package. The corresponding standalone browser build is called `react.js`, and it exports a global called `React`.
|
||||
|
||||
>**Note:**
|
||||
>
|
||||
>Until very recently, `react` npm package and `react.js` standalone build contained all React code (including React DOM) rather than just the core. This was done for backwards compatibility and historical reasons. Since React 15.4.0, the core is better separated in the build output.
|
||||
>
|
||||
>There is also an additional standalone browser build called `react-with-addons.js` which we will consider separately further below.
|
||||
|
||||
### Renderers
|
||||
|
||||
React was originally created for the DOM but it was later adapted to also support native platforms with [React Native](http://facebook.github.io/react-native/). This introduced the concept of "renderers" to React internals.
|
||||
|
||||
**Renderers manage how a React tree turns into the underlying platform calls.**
|
||||
|
||||
Renderers are located in [`src/renderers`](https://github.com/facebook/react/tree/master/src/renderers/):
|
||||
|
||||
* [React DOM Renderer](https://github.com/facebook/react/tree/master/src/renderers/dom) renders React components to the DOM. It implements [top-level `ReactDOM` APIs](/react/docs/top-level-api.html#reactdom) and is available as [`react-dom`](https://www.npmjs.com/package/react-dom) npm package. It can also be used as standalone browser bundle called `react-dom.js` that exports a `ReactDOM` global.
|
||||
* [React Native Renderer](https://github.com/facebook/react/tree/master/src/renderers/native) renders React components to native views. It is used internally by React Native via [`react-native-renderer`](https://www.npmjs.com/package/react-native-renderer) npm package. In the future a copy of it may get checked into the React Native [repository](https://github.com/facebook/react-native) so that React Native can update React at its own pace.
|
||||
* [React Test Renderer](https://github.com/facebook/react/tree/master/src/renderers/testing) renders React components to JSON trees. It is used by the [Snapshot Testing](https://facebook.github.io/jest/blog/2016/07/27/jest-14.html) feature of [Jest](https://facebook.github.io/jest) and is available as [react-test-renderer](https://www.npmjs.com/package/react-test-renderer) npm package.
|
||||
|
||||
The only other officially supported renderer is [`react-art`](https://github.com/reactjs/react-art). To avoid accidentally breaking it as we make changes to React, we checked it in as [`src/renderers/art`](https://github.com/facebook/react/tree/master/src/renderers/art) and run its test suite. Nevertheless its [GitHub repository](https://github.com/reactjs/react-art) still acts as the source of truth.
|
||||
|
||||
While it is [technically possible](https://github.com/iamdustan/tiny-react-renderer) to create custom React renderer, this is currently not officially supported. There is no stable public contract for custom renderers yet which is another reason why we keep them all in a single place.
|
||||
|
||||
>**Note:**
|
||||
>
|
||||
>Technically the [`native`](https://github.com/facebook/react/tree/master/src/renderers/native) renderer is a very thin layer that teaches React to interact with React Native implementation. The real platform-specific code managing the native views lives in the [React Native repository](https://github.com/facebook/react-native) together with its components.
|
||||
|
||||
### Reconcilers
|
||||
|
||||
Even vastly different renderers like React DOM and React Native need to share a lot of logic. In particular, the [reconciliation](/react/docs/reconciliation.html) algorithm should be as similar as possible so that declarative rendering, custom components, state, lifecycle methods, and refs work consistently across platforms.
|
||||
|
||||
To solve this, different renderers share some code between them. We call this part of React a "reconciler". When an update such as `setState()` is scheduled, the reconciler calls `render()` on components in the tree and mounts, updates, or unmounts them.
|
||||
|
||||
Reconcilers are not packaged separately because they currently have no public API. Instead, they are exclusively used by renderers such as React DOM and React Native.
|
||||
|
||||
### Stack Reconciler
|
||||
|
||||
The "stack" reconciler is the one powering all React production code today. It is located in [`src/renderers/shared/stack/reconciler`](https://github.com/facebook/react/tree/master/src/renderers/shared/stack) and is used by both React DOM and React Native.
|
||||
|
||||
It is written in an [object-oriented way](https://en.wikipedia.org/wiki/Composite_pattern) and maintains a separate tree of "internal instances" for all React components. The internal instances exist both for user-defined ("composite") and platform-specific ("host") components. The internal instances are inaccessible directly to the user, and their tree is never exposed.
|
||||
|
||||
When a component mounts, updates, or unmounts, the stack reconciler calls a method on that internal instance. The methods are called `mountComponent(element)`, `receiveComponent(nextElement)`, and `unmountComponent(element)`.
|
||||
|
||||
#### Host Components
|
||||
|
||||
Platform-specific ("host") components, such as `<div>` or a `<View>`, run platform-specific code. For example, React DOM instructs the stack reconciler to use [`ReactDOMComponent`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js) to handle [mounting](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js#L517), [updates](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js#L865), and [unmounting](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js#L1140) of DOM components.
|
||||
|
||||
Regardless of the platform, both `<div>` and `<View>` handle managing multiple children in a similar way. For convenience, the stack reconciler provides a helper called [`ReactMultiChild`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactMultiChild.js) that both DOM and Native renderers [use](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js#L1203).
|
||||
|
||||
#### Composite Components
|
||||
|
||||
User-defined ("composite") components should behave the same way with all renderers. This is why the stack reconciler provides a shared implementation in [`ReactCompositeComponent`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js). It is always the same regardless of the renderer.
|
||||
|
||||
Composite components also implement [mounting](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js#L181), [updating](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js#L703), and [unmounting](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js#L524). However, unlike host components, `ReactCompositeComponent` needs to behave differently depending on user's code. This is why it calls methods, such as `render()` and `componentDidMount()`, on the user-supplied class.
|
||||
|
||||
During an update, `ReactCompositeComponent` checks whether the `render()` output has a different `type` or `key` than the last time. If neither `type` nor `key` has changed, it delegates the update to the existing child internal instance. Otherwise, it unmounts the old child instance, and mounts a new one. This is described in the [reconciliation algorithm](/react/docs/reconciliation.html).
|
||||
|
||||
#### Recursion
|
||||
|
||||
During an update, the stack reconciler "drills down" through composite components, runs their `render()` methods, and decides whether to update or replace their single child instance. It executes platform-specific code as it passes through the host components like `<div>` and `<View>`. Host components may have multiple children which are also processed recursively.
|
||||
|
||||
It is important to understand that the stack reconciler always processes the component tree synchronously in a single pass. While individual tree branches may [bail out of reconciliation](/react/docs/advanced-performance.html#avoiding-reconciling-the-dom), the stack reconciler can't pause, and so it is suboptimal when the updates are deep and the available CPU time is limited.
|
||||
|
||||
### Fiber Reconciler
|
||||
|
||||
The "fiber" reconciler is a new effort aiming to resolve the problems inherent in the stack reconciler and fix a few long-standing issues.
|
||||
|
||||
It is a complete rewrite of the reconciler, and is currently [in active development](https://github.com/facebook/react/pulls?utf8=%E2%9C%93&q=is%3Apr%20is%3Aopen%20fiber).
|
||||
|
||||
Its main goals are:
|
||||
|
||||
* Ability to split interruptible work in chunks.
|
||||
* Ability to prioritize, rebase and reuse work in progress.
|
||||
* Ability to yield back and forth between parents and children to support layout in React.
|
||||
* Ability to return multiple elements from `render()`.
|
||||
* Better support for error boundaries.
|
||||
|
||||
You can read more about it in [React Fiber Architecture](https://github.com/acdlite/react-fiber-architecture). At this moment, it is still very experimental, and far from feature parity with the stack reconciler.
|
||||
|
||||
Its source code is located in [`src/renderers/shared/fiber`](https://github.com/facebook/react/tree/master/src/renderers/shared/fiber).
|
||||
|
||||
### Event System
|
||||
|
||||
React implements a synthetic event system which is agnostic of the renderers and works both with React DOM and React Native. Its source code is located in [`src/renderers/shared/stack/event`](https://github.com/facebook/react/tree/master/src/renderers/shared/stack/event).
|
||||
|
||||
There is a [video with a deep code dive into it](https://www.youtube.com/watch?v=dRo_egw7tBc) (66 mins).
|
||||
|
||||
### Add-ons
|
||||
|
||||
Each of the [React add-ons](/react/docs/addons.html) ships as a separate package on npm with a `react-addons-` prefix. Their source is located in [`src/addons`](https://github.com/facebook/react/tree/master/src/addons) with the exception of [`ReactPerf`](https://github.com/facebook/react/blob/master/src/renderers/shared/ReactPerf.js) and [`ReactTestUtils`](https://github.com/facebook/react/blob/master/src/test/ReactTestUtils.js).
|
||||
|
||||
Additionally, we provide a standalone build called `react-with-addons.js` which includes React core *and* all add-ons exposed on the `addons` field of the `React` global object.
|
||||
|
||||
### What Next?
|
||||
|
||||
Learn the [design principles](/react/contributing/design-principles.html) guiding development of React in the next section.
|
||||
161
docs/contributing/design-principles.md
Normal file
161
docs/contributing/design-principles.md
Normal file
@@ -0,0 +1,161 @@
|
||||
---
|
||||
id: design-principles
|
||||
title: Design Principles
|
||||
layout: contributing
|
||||
permalink: contributing/design-principles.html
|
||||
prev: codebase-overview.html
|
||||
---
|
||||
|
||||
We wrote this document so that you have a better idea of how we decide what React does and what React doesn't do, and what our development philosophy is like. While we are excited to see community contributions, we are not likely to choose a path that violates one or more of these principles.
|
||||
|
||||
>**Note:**
|
||||
>
|
||||
>This document assumes a strong understanding of React. It describes the design principles of *React itself*, not React components or applications.
|
||||
>
|
||||
>For an introduction to React, check out [Thinking in React](/react/docs/thinking-in-react.html) instead.
|
||||
|
||||
### Composition
|
||||
|
||||
The key feature of React is composition of components. Components written by different people should work well together. It is important to us that you can add functionality to a component without causing rippling changes throughout the codebase.
|
||||
|
||||
For example, it should be possible to introduce some local state into a component without changing any of the components using it. Similarly, it should be possible to add some initialization and teardown code to any component when necessary.
|
||||
|
||||
There is nothing "bad" about using state or lifecycle hooks in components. Like any powerful features, they should be used in moderation, but we have no intention to remove them. On the contrary, we think they are integral parts of what makes React useful. We might enable [more functional patterns](https://github.com/reactjs/react-future/tree/master/07%20-%20Returning%20State) in the future, but both local state and lifecycle hooks will be a part of that model.
|
||||
|
||||
Components are often described as "just functions" but in our view they need to be more than that to be useful. In React, components describe any composable behavior, and this includes rendering, lifecycle, and state. Some external libraries like [Relay](http://facebook.github.io/relay/) augment components with other responsibilities such as describing data dependencies. It is possible that those ideas might make it back into React too in some form.
|
||||
|
||||
### Common Abstraction
|
||||
|
||||
In general we [resist adding features](https://www.youtube.com/watch?v=4anAwXYqLG8) that can be implemented in userland. We don't want to bloat your apps with useless library code. However, there are exceptions to this.
|
||||
|
||||
For example, if React didn't provide support for local state or lifecycle hooks, people would create custom abstractions for them. When there are multiple abstractions competing, React can't enforce or take advantage of the properties of either of them. It has to work with the lowest common denominator.
|
||||
|
||||
This is why sometimes we add features to React itself. If we notice that many components implement a certain feature in incompatible or inefficient ways, we might prefer to bake it into React. We don't do it lightly. When we do it, it's because we are confident that raising the abstraction level benefits the whole ecosystem. State, lifecycle hooks, cross-browser event normalization are good examples of this.
|
||||
|
||||
We always discuss such improvement proposals with the community. You can find some of those discussions by the [“big picture”](https://github.com/facebook/react/issues?q=is%3Aopen+is%3Aissue+label%3A%22big+picture%22) label on the React issue tracker.
|
||||
|
||||
### Escape Hatches
|
||||
|
||||
React is pragmatic. It is driven by the needs of the products written at Facebook. While it is influenced by some paradigms that are not yet fully mainstream such as functional programming, staying accessible to a wide range of developers with different skills and experience levels is an explicit goal of the project.
|
||||
|
||||
If we want to deprecate a pattern that we don't like, it is our responsibility to consider all existing use cases for it and [educate the community about the alternatives](/react/blog/2016/07/13/mixins-considered-harmful.html) before we deprecate it. If some pattern that is useful for building apps is hard to express in a declarative way, we will [provide an imperative API](/react/docs/more-about-refs.html) for it. If we can't figure out a perfect API for something that we found necessary in many apps, we will [provide a temporary subpar working API](/react/docs/context.html) as long as it is possible to get rid of it later and it leaves the door open for future improvements.
|
||||
|
||||
### Stability
|
||||
|
||||
We value API stability. At Facebook, we have more than 20 thousand components using React. Many other companies, including [Twitter](https://twitter.com/) and [Airbnb](https://www.airbnb.com/), are also heavy users of React. This is why we are usually reluctant to change public APIs or behavior.
|
||||
|
||||
However we think stability in the sense of "nothing changes" is overrated. It quickly turns into stagnation. Instead, we prefer the stability in the sense of "It is heavily used in production, and when something changes, there is a clear (and preferably automated) migration path."
|
||||
|
||||
When we deprecate a pattern, we study its internal usage at Facebook and add deprecation warnings. They let us assess the impact of the change. Sometimes we back out if we see that it is too early, and we need to think more strategically about getting the codebases to the point where they are ready for this change.
|
||||
|
||||
If we are confident that the change is not too disruptive and the migration strategy is viable for all use cases, we release the deprecation warning to the open source community. We are closely in touch with many users of React outside of Facebook, and we monitor popular open source projects and guide them in fixing those deprecations.
|
||||
|
||||
Given the sheer size of the Facebook React codebase, successful internal migration is often a good indicator that other companies won't have problems either. Nevertheless sometimes people point out additional use cases we haven't thought of, and we add escape hatches for them or rethink our approach.
|
||||
|
||||
We don't deprecate anything without a good reason. We recognize that sometimes deprecations warnings cause frustration but we add them because deprecations clean up the road for the improvements and new features that we and many people in the community consider valuable.
|
||||
|
||||
For example, we added a [warning about unknown DOM props](/react/warnings/unknown-prop.html) in React 15.2.0. Many projects were affected by this. However fixing this warning is important so that we can introduce the support for [custom attributes](https://github.com/facebook/react/issues/140) to React. There is a reason like this behind every deprecation that we add.
|
||||
|
||||
When we add a deprecation warning, we keep it for the rest of the current major version, and [change the behavior in the next major version](/react/blog/2016/02/19/new-versioning-scheme.html). If there is a lot of repetitive manual work involved, we release a [codemod](https://www.youtube.com/watch?v=d0pOgY8__JM) script that automates most of the change. Codemods enable us to move forward without stagnation in a massive codebase, and we encourage you to use them as well.
|
||||
|
||||
You can find the codemods that we released in the [react-codemod](https://github.com/reactjs/react-codemod) repository.
|
||||
|
||||
### Interoperability
|
||||
|
||||
We place high value in interoperability with existing systems and gradual adoption. Facebook has a massive non-React codebase. Its website uses a mix of a server-side component system called XHP, internal UI libraries that came before React, and React itself. It is important to us that any product team can [start using React for a small feature](https://www.youtube.com/watch?v=BF58ZJ1ZQxY) rather than rewrite their code to bet on it.
|
||||
|
||||
This is why React provides escape hatches to work with mutable models, and tries to work well together with other UI libraries. You can wrap an existing imperative UI into a declarative component, and vice versa. This is crucial for gradual adoption.
|
||||
|
||||
### Scheduling
|
||||
|
||||
Even when your components are described as functions, when you use React you don't call them directly. Every component returns a [description of what needs to be rendered](/react/blog/2015/12/18/react-components-elements-and-instances.html#elements-describe-the-tree), and that description may include both user-written components like `<LikeButton>` and platform-specific components like `<div>`. It is up to React to "unroll" `<LikeButton>` at some point in the future and actually apply changes to the UI tree according to the render results of the components recursively.
|
||||
|
||||
This is a subtle distinction but a powerful one. Since you don't call that component function but let React call it, it means React has the power to delay calling it if necessary. In its current implementation React walks the tree recursively and calls render functions of the whole updated tree during a single tick. However in the future it might start [delaying some updates to avoid dropping frames](https://github.com/facebook/react/issues/6170).
|
||||
|
||||
This is a common theme in React design. Some popular libraries implement the "push" approach where computations are performed when the new data is available. React, however, sticks to the "pull" approach where computations can be delayed until necessary.
|
||||
|
||||
React is not a generic data processing library. It is a library for building user interfaces. We think that it is uniquely positioned in an app to know which computations are relevant right now and which are not.
|
||||
|
||||
If something is offscreen, we can delay any logic related to it. If data is arriving faster than the frame rate, we can coalesce and batch updates. We can prioritize work coming from user interactions (such as an animation caused by a button click) over less important background work (such as rendering new content just loaded from the network) to avoid dropping frames.
|
||||
|
||||
To be clear, we are not taking advantage of this right now. However the freedom to do something like this is why we prefer to have control over scheduling, and why `setState()` is asynchronous. Conceptually, we think of it as "scheduling an update".
|
||||
|
||||
The control over scheduling would be harder for us to gain if we let the user directly compose views with a "push" based paradigm common in some variations of [Functional Reactive Programming](https://en.wikipedia.org/wiki/Functional_reactive_programming). We want to own the "glue" code.
|
||||
|
||||
It is a key goal for React that the amount of the user code that executes before yielding back into React is minimal. This ensures that React retains the capability to schedule and split work in chunks according to what it knows about the UI.
|
||||
|
||||
There is an internal joke in the team that React should have been called "Schedule" because React does not want to be fully "reactive".
|
||||
|
||||
### Developer Experience
|
||||
|
||||
Providing a good developer experience is important to us.
|
||||
|
||||
For example, we maintain [React DevTools](https://github.com/facebook/react-devtools) which let you inspect the React component tree in Chrome and Firefox. We have heard that it brings a big productivity boost both to the Facebook engineers and to the community.
|
||||
|
||||
We also try to go an extra mile to provide helpful developer warnings. For example, React warns you in development if you nest tags in a way that the browser doesn't understand, or if you make a common typo in the API. Developer warnings and the related checks are the main reason why the development version of React is slower than the production version.
|
||||
|
||||
The usage patterns that we see internally at Facebook help us understand what the common mistakes are, and how to prevent them early. When we add new features, we try to anticipate the common mistakes and warn about them.
|
||||
|
||||
We are always looking out for ways to improve the developer experience. We love to hear your suggestions and accept your contributions to make it even better.
|
||||
|
||||
### Debugging
|
||||
|
||||
When something goes wrong, it is important that you have breadcrumbs to trace the mistake to its source in the codebase. In React, props and state are those breadcrumbs.
|
||||
|
||||
If you see something wrong on the screen, you can open React DevTools, find the component responsible for rendering, and then see if the props and state are correct. If they are, you know that the problem is in the component’s `render()` function, or some function that is called by `render()`. The problem is isolated.
|
||||
|
||||
If the state is wrong, you know that the problem is caused by one of the `setState()` calls in this file. This, too, is relatively simple to locate and fix because usually there are only a few `setState()` calls in a single file.
|
||||
|
||||
If the props are wrong, you can traverse the tree up in the inspector, looking for the component that first "poisoned the well" by passing bad props down.
|
||||
|
||||
This ability to trace any UI to the data that produced it in the form of current props and state is very important to React. It is an explicit design goal that state is not "trapped" in closures and combinators, and is available to React directly.
|
||||
|
||||
While the UI is dynamic, we believe that synchronous `render()` functions of props and state turn debugging from guesswork into a boring but finite procedure. We would like to preserve this constraint in React even though it makes some use cases, like complex animations, harder.
|
||||
|
||||
### Configuration
|
||||
|
||||
We find global runtime configuration options to be problematic.
|
||||
|
||||
For example, it is occasionally requested that we implement a function like `React.configure(options)` or `React.register(component)`. However this poses multiple problems, and we are not aware of good solutions to them.
|
||||
|
||||
What if somebody calls such a function from a third-party component library? What if one React app embeds another React app, and their desired configurations are incompatible? How can a third-party component specify that it requires a particular configuration? We think that global configuration doesn't work well with composition. Since composition is central to React, we don't provide global configuration in code.
|
||||
|
||||
We do, however, provide some global configuration on the build level. For example, we provide separate development and production builds. We may also [add a profiling build](https://github.com/facebook/react/issues/6627) in the future, and we are open to considering other build flags.
|
||||
|
||||
### Beyond the DOM
|
||||
|
||||
We see the value of React in the way it allows us to write components that have less bugs and compose together well. DOM is the original rendering target for React but [React Native](http://facebook.github.io/react-native/) is just as important both to Facebook and the community.
|
||||
|
||||
Being renderer-agnostic is an important design constraint of React. It adds some overhead in the internal representations. On the other hand, any improvements to the core translate across platforms.
|
||||
|
||||
Having a single programming model lets us form engineering teams around products instead of platforms. So far the tradeoff has been worth it for us.
|
||||
|
||||
### Implementation
|
||||
|
||||
We try to provide elegant APIs where possible. We are much less concerned with the implementation being elegant. The real world is far from perfect, and to a reasonable extent we prefer to put the ugly code into the library if it means the user does not have to write it. When we evaluate new code, we are looking for an implementation that is correct, performant and affords a good developer experience. Elegance is secondary.
|
||||
|
||||
We prefer boring code to clever code. Code is disposable and often changes. So it is important that it [doesn't introduce new internal abstractions unless absolutely necessary](https://youtu.be/4anAwXYqLG8?t=13m9s). Verbose code that is easy to move around, change and remove is preferred to elegant code that is prematurely abstracted and hard to change.
|
||||
|
||||
### Optimized for Tooling
|
||||
|
||||
Some commonly used APIs have verbose names. For example, we use `componentDidMount()` instead of `didMount()` or `onMount()`. This is [intentional](https://github.com/reactjs/react-future/issues/40#issuecomment-142442124). The goal is to make the points of interaction with the library highly visible.
|
||||
|
||||
In a massive codebase like Facebook, being able to search for uses of specific APIs is very important. We value distinct verbose names, and especially for the features that should be used sparingly. For example, `dangerouslySetInnerHTML` is hard to miss in a code review.
|
||||
|
||||
Optimizing for search is also important because of our reliance on [codemods](https://www.youtube.com/watch?v=d0pOgY8__JM) to make breaking changes. We want it to be easy and safe to apply vast automated changes across the codebase, and unique verbose names help us achieve this. Similarly, distinctive names make it easy to write custom [lint rules](https://github.com/yannickcr/eslint-plugin-react) about using React without worrying about potential false positives.
|
||||
|
||||
[JSX](/react/docs/displaying-data.html#jsx-syntax) plays a similar role. While it is not required with React, we use it extensively at Facebook both for aesthetic and pragmatic reasons.
|
||||
|
||||
In our codebase, JSX provides an unambigious hint to the tools that they are dealing with a React element tree. This makes it possible to add build-time optimizations such as [hoisting constant elements](http://babeljs.io/docs/plugins/transform-react-constant-elements/), safely lint and codemod internal component usage, and [include JSX source location](https://github.com/facebook/react/pull/6771) into the warnings.
|
||||
|
||||
### Dogfooding
|
||||
|
||||
We try our best to address the problems raised by the community. However we are likely to prioritize the issues that people are *also* experiencing internally at Facebook. Perhaps counter-intuitively, we think this is the main reason why the community can bet on React.
|
||||
|
||||
Heavy internal usage gives us the confidence that React won't disappear tomorrow. React was created at Facebook to solve its problems. It brings tangible business value to the company and is used in many of its products. [Dogfooding](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) it means that our vision stays sharp and we have a focused direction going forward.
|
||||
|
||||
This doesn't mean that we ignore the issues raised by the community. For example, we added support for [web components](/react/docs/webcomponents.html) and [SVG](https://github.com/facebook/react/pull/6243) to React even though we don't rely on either of them internally. We are actively [listening to your pain points](https://github.com/facebook/react/issues/2686) and [address them](/react/blog/2016/07/11/introducing-reacts-error-code-system.html) to the best of our ability. The community is what makes React special to us, and we are honored to contribute back.
|
||||
|
||||
After releasing many open source projects at Facebook, we have learned that trying to make everyone happy at the same time produced projects with poor focus that didn't grow well. Instead, we found that picking a small audience and focusing on making them happy brings a positive net effect. That's exactly what we did with React, and so far solving the problems encountered by Facebook product teams has translated well to the open source community.
|
||||
|
||||
The downside of this approach is that sometimes we fail to give enough focus to the things that Facebook teams don't have to deal with, such as the "getting started" experience. We are acutely aware of this, and we are thinking of how to improve in a way that would benefit everyone in the community without making the same mistakes we did with open source projects before.
|
||||
159
docs/contributing/how-to-contribute.md
Normal file
159
docs/contributing/how-to-contribute.md
Normal file
@@ -0,0 +1,159 @@
|
||||
---
|
||||
id: how-to-contribute
|
||||
title: How to Contribute
|
||||
layout: contributing
|
||||
permalink: contributing/how-to-contribute.html
|
||||
next: codebase-overview.html
|
||||
---
|
||||
|
||||
React is one of Facebook's first open source projects that is both under very active development and is also being used to ship code to everybody on [facebook.com](https://www.facebook.com). We're still working out the kinks to make contributing to this project as easy and transparent as possible, but we're not quite there yet. Hopefully this document makes the process for contributing clear and answers some questions that you may have.
|
||||
|
||||
### [Code of Conduct](https://code.facebook.com/codeofconduct)
|
||||
|
||||
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read [the full text](https://code.facebook.com/codeofconduct) so that you can understand what actions will and will not be tolerated.
|
||||
|
||||
### Open Development
|
||||
|
||||
All work on React happens directly on [GitHub](https://github.com/facebook/react). Both core team members and external contributors send pull requests which go through the same review process.
|
||||
|
||||
### Branch Organization
|
||||
|
||||
We will do our best to keep the [`master` branch](https://github.com/facebook/react/tree/master) in good shape, with tests passing at all times. But in order to move fast, we will make API changes that your application might not be compatible with. We recommend that you use [the latest stable version of React](/react/downloads.html).
|
||||
|
||||
If you send a pull request, please do it against the `master` branch. We maintain stable branches for major versions separately but we don't accept pull requests to them directly. Instead, we cherry-pick non-breaking changes from master to the latest stable major version.
|
||||
|
||||
### Semantic Versioning
|
||||
|
||||
React follows [semantic versioning](http://semver.org/). We release patch versions for bugfixes, minor versions for new features, and major versions for any breaking changes. When we make breaking changes, we also introduce deprecation warnings in a minor version so that our users learn about the upcoming changes and migrate their code in advance.
|
||||
|
||||
We tag every pull request with a label marking whether the change should go in the next [patch](https://github.com/facebook/react/pulls?q=is%3Aopen+is%3Apr+label%3Asemver-patch), [minor](https://github.com/facebook/react/pulls?q=is%3Aopen+is%3Apr+label%3Asemver-minor), or a [major](https://github.com/facebook/react/pulls?q=is%3Aopen+is%3Apr+label%3Asemver-major) version. We release new patch versions every few weeks, minor versions every few months, and major versions one or two times a year.
|
||||
|
||||
Every significant change is documented in the [changelog file](https://github.com/facebook/react/blob/master/CHANGELOG.md).
|
||||
|
||||
### Bugs
|
||||
|
||||
#### Where to Find Known Issues
|
||||
|
||||
We are using [GitHub Issues](https://github.com/facebook/react/issues) for our public bugs. We keep a close eye on this and try to make it clear when we have an internal fix in progress. Before filing a new task, try to make sure your problem doesn't already exist.
|
||||
|
||||
#### Reporting New Issues
|
||||
|
||||
The best way to get your bug fixed is to provide a reduced test case. This [JSFiddle template](https://jsfiddle.net/reactjs/69z2wepo/) is a great starting point.
|
||||
|
||||
#### Security Bugs
|
||||
|
||||
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe disclosure of security bugs. With that in mind, please do not file public issues; go through the process outlined on that page.
|
||||
|
||||
### How to Get in Touch
|
||||
|
||||
* IRC: [#reactjs on freenode](https://webchat.freenode.net/?channels=reactjs)
|
||||
* Discussion forum: [discuss.reactjs.org](https://discuss.reactjs.org/)
|
||||
|
||||
There is also [an active community of React users on the Discord chat platform](http://www.reactiflux.com/) in case you need help with React.
|
||||
|
||||
### Proposing a Change
|
||||
|
||||
If you intend to change to the public API, or make any non-trivial changes to the implementation, we recommend [filing an issue](https://github.com/facebook/react/issues/new). This lets us reach an agreement on your proposal before you put significant effort into it.
|
||||
|
||||
If you're only fixing a bug, it's fine to submit a pull request right away but we still recommend to file an issue detailing what you're fixing. This is helpful in case we don't accept that specific fix but want to keep track of the issue.
|
||||
|
||||
### Your First Pull Request
|
||||
|
||||
Working on your first Pull Request? You can learn how from this free video series:
|
||||
|
||||
**[How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)**
|
||||
|
||||
To help you get your feet wet and get you familiar with our contribution process, we have a list of **[good first bugs](https://github.com/facebook/react/labels/good%20first%20bug)** that contain bugs which are fairly easy to fix. This is a great place to get started.
|
||||
|
||||
If you decide to fix an issue, please be sure to check the comment thread in case somebody is already working on a fix. If nobody is working on it at the moment, please leave a comment stating that you intend to work on it so other people don't accidentally duplicate your effort.
|
||||
|
||||
If somebody claims an issue but doesn't follow up for more than two weeks, it's fine to take over it but you should still leave a comment.
|
||||
|
||||
### Sending a Pull Request
|
||||
|
||||
The core team is monitoring for pull requests. We will review your pull request and either merge it, request changes to it, or close it with an explanation. For API changes we may need to fix our internal uses at Facebook.com, which could cause some delay. We'll do our best to provide updates and feedback throughout the process.
|
||||
|
||||
**Before submitting a pull request,** please make sure the following is done:
|
||||
|
||||
1. Fork [the repository](https://github.com/facebook/react) and create your branch from `master`.
|
||||
2. If you've added code that should be tested, add tests!
|
||||
3. If you've changed APIs, update the documentation.
|
||||
4. Ensure the test suite passes (`npm test`).
|
||||
5. Make sure your code lints (`npm run lint`).
|
||||
6. If you haven't already, complete the CLA.
|
||||
|
||||
### Contributor License Agreement (CLA)
|
||||
|
||||
In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Facebook open source project, you're good to go. If you are submitting a pull request for the first time, just let us know that you have completed the CLA and we can cross-check with your GitHub username.
|
||||
|
||||
**[Complete your CLA here.](https://code.facebook.com/cla)**
|
||||
|
||||
### Contribution Prerequisites
|
||||
|
||||
* You have `node` installed at v4.0.0+ and `npm` at v2.0.0+.
|
||||
* You have `gcc` installed or are comfortable installing a compiler if needed. Some of our `npm` dependencies may require a compilation step. On OS X, the Xcode Command Line Tools will cover this. On Ubuntu, `apt-get install build-essential` will install the required packages. Similar commands should work on other Linux distros. Windows will require some additional steps, see the [`node-gyp` installation instructions](https://github.com/nodejs/node-gyp#installation) for details.
|
||||
* You are familiar with `npm` and know whether or not you need to use `sudo` when installing packages globally.
|
||||
* You are familiar with `git`.
|
||||
|
||||
### Development Workflow
|
||||
|
||||
After cloning React, run `npm install` to fetch its dependencies.
|
||||
Then, you can run several commands:
|
||||
|
||||
* `npm run lint` checks the code style.
|
||||
* `npm test` runs the complete test suite.
|
||||
* `npm test -- --watch` runs an interactive test watcher.
|
||||
* `npm test <pattern>` runs tests with matching filenames.
|
||||
* `npm run build` creates a `build` folder with all the packages.
|
||||
|
||||
We recommend running `npm test` (or its variations above) to make sure you don't introduce any regressions as you work on your change. However it can be handy to try your build of React in a real project.
|
||||
|
||||
First, run `npm run build`. This will produce pre-built bundles in `build` folder, as well as prepare npm packages inside `build/packages`.
|
||||
|
||||
The easiest way to try your changes is to open and modify `examples/basic/index.html`. This file already uses `react.js` from the `build` folder so it will pick up your changes. Please make sure to rollback any unintentional changes in `examples` before sending a pull request.
|
||||
|
||||
If you want to try your changes in your existing React project, you may copy `build/react.js`, `build/react-dom.js`, or any other build products into your app and use them instead of the stable version. If your project uses React from npm, you may delete `react` and `react-dom` in its dependencies and use `npm link` to point them to your local `build` folder:
|
||||
|
||||
```sh
|
||||
cd your_project
|
||||
rm -rf node_modules/react
|
||||
rm -rf node_modules/react-dom
|
||||
npm link ~/path_to_your_react_clone/build/packages/react
|
||||
npm link ~/path_to_your_react_clone/build/packages/react-dom
|
||||
```
|
||||
|
||||
Every time you run `npm run build` in the React folder, the updated versions will appear in your project's `node_modules`. You can then rebuild your project to try your changes.
|
||||
|
||||
We still require that your pull request contains unit tests for any new functionality. This way we can ensure that we don't break your code in the future.
|
||||
|
||||
### Style Guide
|
||||
|
||||
Our linter will catch most styling issues that may exist in your code.
|
||||
You can check the status of your code styling by simply running `npm run lint`.
|
||||
|
||||
However, there are still some styles that the linter cannot pick up. If you are unsure about something, looking at [Airbnb's Style Guide](https://github.com/airbnb/javascript) will guide you in the right direction.
|
||||
|
||||
### Code Conventions
|
||||
|
||||
* Use semicolons `;`
|
||||
* Commas last `,`
|
||||
* 2 spaces for indentation (no tabs)
|
||||
* Prefer `'` over `"`
|
||||
* `'use strict';`
|
||||
* 80 character line length (**except documentation**)
|
||||
* Write "attractive" code
|
||||
* Do not use the optional parameters of `setTimeout` and `setInterval`
|
||||
|
||||
### License
|
||||
|
||||
By contributing to React, you agree that your contributions will be licensed under its BSD license.
|
||||
|
||||
### Meeting Notes
|
||||
|
||||
React team meets once a week to discuss the development of React, future plans, and priorities. You can find the meeting notes in a [dedicated repository](https://github.com/reactjs/core-notes/).
|
||||
|
||||
### What Next?
|
||||
|
||||
You may be interested in watching [this short video](https://www.youtube.com/watch?v=wUpPsEcGsg8) (26 mins) which gives an introduction on how to contribute to React.
|
||||
|
||||
Read the next sections to learn more about [understanding the codebase](/react/contributing/codebase-overview.html), and the [design principles](/react/contributing/design-principles.html) guiding the development of React.
|
||||
@@ -18,7 +18,7 @@
|
||||
padding: 0 14px; /* Horizontal padding of content */
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler {
|
||||
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||
background-color: white; /* The little square between H and V scrollbars */
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
.CodeMirror-gutters {
|
||||
border-right: 1px solid #ddd;
|
||||
background-color: #f7f7f7;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.CodeMirror-linenumbers {}
|
||||
.CodeMirror-linenumber {
|
||||
@@ -34,68 +35,110 @@
|
||||
min-width: 20px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.CodeMirror-guttermarker { color: black; }
|
||||
.CodeMirror-guttermarker-subtle { color: #999; }
|
||||
|
||||
/* CURSOR */
|
||||
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
.CodeMirror-cursor {
|
||||
border-left: 1px solid black;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
}
|
||||
/* Shown when moving in bi-directional text */
|
||||
.CodeMirror div.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
|
||||
.cm-fat-cursor .CodeMirror-cursor {
|
||||
width: auto;
|
||||
border: 0 !important;
|
||||
background: #7e7;
|
||||
}
|
||||
.cm-fat-cursor div.CodeMirror-cursors {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.cm-animate-fat-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
background: rgba(0, 200, 0, .4);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
|
||||
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||
-moz-animation: blink 1.06s steps(1) infinite;
|
||||
animation: blink 1.06s steps(1) infinite;
|
||||
background-color: #7e7;
|
||||
}
|
||||
/* Kludge to turn off filter in ie9+, which also accepts rgba */
|
||||
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor:not(#nonsense_id) {
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
@-moz-keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
@-webkit-keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
@keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
|
||||
/* Can style cursor different in overwrite (non-insert) mode */
|
||||
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
|
||||
.CodeMirror-overwrite .CodeMirror-cursor {}
|
||||
|
||||
.cm-tab { display: inline-block; text-decoration: inherit; }
|
||||
|
||||
.CodeMirror-ruler {
|
||||
border-left: 1px solid #ccc;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* DEFAULT THEME */
|
||||
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-negative {color: #d44;}
|
||||
.cm-positive {color: #292;}
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
.cm-strikethrough {text-decoration: line-through;}
|
||||
|
||||
.cm-s-default .cm-keyword {color: #708;}
|
||||
.cm-s-default .cm-atom {color: #219;}
|
||||
.cm-s-default .cm-number {color: #164;}
|
||||
.cm-s-default .cm-def {color: #00f;}
|
||||
.cm-s-default .cm-variable {color: black;}
|
||||
.cm-s-default .cm-variable,
|
||||
.cm-s-default .cm-punctuation,
|
||||
.cm-s-default .cm-property,
|
||||
.cm-s-default .cm-operator {}
|
||||
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||
.cm-s-default .cm-variable-3 {color: #085;}
|
||||
.cm-s-default .cm-property {color: black;}
|
||||
.cm-s-default .cm-operator {color: black;}
|
||||
.cm-s-default .cm-comment {color: #a50;}
|
||||
.cm-s-default .cm-string {color: #a11;}
|
||||
.cm-s-default .cm-string-2 {color: #f50;}
|
||||
.cm-s-default .cm-meta {color: #555;}
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-s-default .cm-qualifier {color: #555;}
|
||||
.cm-s-default .cm-builtin {color: #30a;}
|
||||
.cm-s-default .cm-bracket {color: #997;}
|
||||
.cm-s-default .cm-tag {color: #170;}
|
||||
.cm-s-default .cm-attribute {color: #00c;}
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-s-default .cm-hr {color: #999;}
|
||||
.cm-s-default .cm-link {color: #00c;}
|
||||
|
||||
.cm-negative {color: #d44;}
|
||||
.cm-positive {color: #292;}
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-emstrong {font-style: italic; font-weight: bold;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
||||
.CodeMirror-composing { border-bottom: 2px solid; }
|
||||
|
||||
/* Default styles for common addons */
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
|
||||
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||
|
||||
/* STOP */
|
||||
|
||||
@@ -103,28 +146,30 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
the editor. You probably shouldn't touch them. */
|
||||
|
||||
.CodeMirror {
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
overflow: scroll !important; /* Things will break if this is overridden */
|
||||
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||
/* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
|
||||
/* See overflow: hidden in .CodeMirror */
|
||||
margin-bottom: -30px; margin-right: -30px;
|
||||
padding-bottom: 30px; padding-right: 30px;
|
||||
padding-bottom: 30px;
|
||||
height: 100%;
|
||||
outline: none; /* Prevent dragging from highlighting the element */
|
||||
position: relative;
|
||||
}
|
||||
.CodeMirror-sizer {
|
||||
position: relative;
|
||||
border-right: 30px solid transparent;
|
||||
}
|
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||
before actual scrolling happens, thus preventing shaking and
|
||||
flickering artifacts. */
|
||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
|
||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
display: none;
|
||||
@@ -141,33 +186,55 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
}
|
||||
.CodeMirror-scrollbar-filler {
|
||||
right: 0; bottom: 0;
|
||||
z-index: 6;
|
||||
}
|
||||
.CodeMirror-gutter-filler {
|
||||
left: 0; bottom: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
position: absolute; left: 0; top: 0;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
z-index: 3;
|
||||
}
|
||||
.CodeMirror-gutter {
|
||||
white-space: normal;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-bottom: -30px;
|
||||
/* Hack to make IE7 behave */
|
||||
*zoom:1;
|
||||
*display:inline;
|
||||
}
|
||||
.CodeMirror-gutter-wrapper {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
.CodeMirror-gutter-background {
|
||||
position: absolute;
|
||||
top: 0; bottom: 0;
|
||||
z-index: 4;
|
||||
}
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
}
|
||||
.CodeMirror-gutter-wrapper {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.CodeMirror-lines {
|
||||
cursor: text;
|
||||
min-height: 1px; /* prevents collapsing before first draw */
|
||||
}
|
||||
.CodeMirror pre {
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
-moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
|
||||
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
|
||||
border-width: 0;
|
||||
background: transparent;
|
||||
font-family: inherit;
|
||||
@@ -180,12 +247,16 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-font-variant-ligatures: none;
|
||||
font-variant-ligatures: none;
|
||||
}
|
||||
.CodeMirror-wrap pre {
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.CodeMirror-linebackground {
|
||||
position: absolute;
|
||||
left: 0; right: 0; top: 0; bottom: 0;
|
||||
@@ -198,30 +269,51 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.CodeMirror-wrap .CodeMirror-scroll {
|
||||
overflow-x: hidden;
|
||||
.CodeMirror-widget {}
|
||||
|
||||
.CodeMirror-code {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Force content-box sizing for the elements where we expect it */
|
||||
.CodeMirror-scroll,
|
||||
.CodeMirror-sizer,
|
||||
.CodeMirror-gutter,
|
||||
.CodeMirror-gutters,
|
||||
.CodeMirror-linenumber {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.CodeMirror-measure {
|
||||
position: absolute;
|
||||
width: 100%; height: 0px;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-cursor { position: absolute; }
|
||||
.CodeMirror-measure pre { position: static; }
|
||||
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
position: absolute;
|
||||
div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
}
|
||||
.CodeMirror-focused div.CodeMirror-cursor {
|
||||
div.CodeMirror-dragcursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-focused div.CodeMirror-cursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-selected { background: #d9d9d9; }
|
||||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||
.CodeMirror-crosshair { cursor: crosshair; }
|
||||
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
|
||||
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
|
||||
|
||||
.cm-searching {
|
||||
background: #ffa;
|
||||
@@ -231,9 +323,18 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
|
||||
.CodeMirror span { *vertical-align: text-bottom; }
|
||||
|
||||
/* Used to force a border model for a node */
|
||||
.cm-force-border { padding-right: .1px; }
|
||||
|
||||
@media print {
|
||||
/* Hide the cursor when printing */
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
.CodeMirror div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* See issue #2901 */
|
||||
.cm-tab-wrap-hack:after { content: ''; }
|
||||
|
||||
/* Help users use markselection to safely style text background */
|
||||
span.CodeMirror-selectedtext { background: none; }
|
||||
|
||||
@@ -340,8 +340,8 @@ h1, h2, h3, h4, h5, h6 {
|
||||
h3 {
|
||||
color: $darkColor;
|
||||
font-size: 24px;
|
||||
line-height: 28px;
|
||||
font-weight: normal;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
p {
|
||||
font-size: 16px;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: why-react-de-DE
|
||||
title: Warum React?
|
||||
permalink: why-react-de-DE.html
|
||||
permalink: docs/why-react-de-DE.html
|
||||
---
|
||||
React ist eine JavaScript-Bibliothek von Facebook und Instagram für Benutzeroberflächen. Man kann sich React als das **V** in **[MVC](https://de.wikipedia.org/wiki/Model_View_Controller)** vorstellen.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: why-react-it-IT
|
||||
title: Perché React?
|
||||
permalink: why-react-it-IT.html
|
||||
permalink: docs/why-react-it-IT.html
|
||||
next: displaying-data-it-IT.html
|
||||
---
|
||||
React è una libreria JavaScript per creare interfacce utente scritta da Facebook e Instagram. A molti piace pensare a React come alla **V** di **[MVC](https://it.wikipedia.org/wiki/Model-View-Controller)**.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: why-react-ja-JP
|
||||
title: なぜReactを使うのでしょうか?
|
||||
permalink: why-react-ja-JP.html
|
||||
permalink: docs/why-react-ja-JP.html
|
||||
next: displaying-data-ja-JP.html
|
||||
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: why-react-ko-KR
|
||||
title: 왜 React인가?
|
||||
permalink: why-react-ko-KR.html
|
||||
permalink: docs/why-react-ko-KR.html
|
||||
next: displaying-data-ko-KR.html
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: why-react
|
||||
title: Why React?
|
||||
permalink: why-react.html
|
||||
permalink: docs/why-react.html
|
||||
next: displaying-data.html
|
||||
---
|
||||
React is a JavaScript library for creating user interfaces by Facebook and Instagram. Many people choose to think of React as the **V** in **[MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)**.
|
||||
|
||||
29
docs/docs/01-why-react.ru-RU.md
Normal file
29
docs/docs/01-why-react.ru-RU.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
id: why-react-ru-RU
|
||||
title: Почему именно React?
|
||||
permalink: docs/why-react-ru-RU.html
|
||||
next: displaying-data-ru-RU.html
|
||||
---
|
||||
React — библиотека JavaScript для создания интерфейсов от команд Facebook и Instagram. Многие ассоциируют React с понятием **View** в паттерне **[MVC](https://ru.wikipedia.org/wiki/Model-View-Controller)**.
|
||||
|
||||
Мы делали React, чтобы решить одну важную задачу: **создавать действительно большие приложения с постоянно меняющимися данными**.
|
||||
|
||||
## Простота
|
||||
|
||||
С React вы всегда точно знаете как будет выглядеть ваше приложение, ведь как только изменятся данные, он мгновенно отобразит эти изменения в интерфейсе.
|
||||
|
||||
## Декларативность
|
||||
|
||||
Как только состояние приложения изменится, React будто нажимает кнопку "обновить" и точно знает, какие части интерфейса надо поменять, а какие нет. Никаких дополнительных инструкций и команд, React сам отслеживает изменения данных и реагирует на них.
|
||||
|
||||
## Создание компонентов, как строительных блоков приложения
|
||||
|
||||
По сути, разработка на React целиком состоит в создании таких компонентов. С React вы *только* тем и занимаетесь, что пишете новые компоненты, те самые строительные блоки, из которых будет строиться приложение. А поскольку они хорошо инскапсулированы, их удобно использовать повторно даже в других проектах, плюс такой код проще тестировать.
|
||||
|
||||
## Уделите этому 5 минут
|
||||
|
||||
React бросает вызов многим устоявшимся идеям и правилам, и на первый взгляд, некоторые из его идей выглядят по меньшей мере странными. [Уделите этому 5 минут](https://signalvnoise.com/posts/3124-give-it-five-minutes) пока читаете эту статью; эти безумные идеи нашли свое применение при создании тысяч компонентов не только для Facebook и Instagram, но и в других крупных проектах.
|
||||
|
||||
## Узнай больше
|
||||
|
||||
Вы можете больше узнать о причинах создания React [отсюда](/react/blog/2013/06/05/why-react.html).
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: why-react-zh-CN
|
||||
title: 为什么使用 React?
|
||||
permalink: why-react-zh-CN.html
|
||||
permalink: docs/why-react-zh-CN.html
|
||||
next: displaying-data-zh-CN.html
|
||||
---
|
||||
React 是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 库。很多人选择将 React 认为是 **[MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)** 中的 **V**(视图)。
|
||||
|
||||
29
docs/docs/01-why-react.zh-TW.md
Normal file
29
docs/docs/01-why-react.zh-TW.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
id: why-react-zh-TW
|
||||
title: Why React?
|
||||
permalink: docs/why-react-zh-TW.html
|
||||
next: displaying-data.html
|
||||
---
|
||||
React是Facebook和Instagram用來建立使用者介面的JavaScript函式庫. 很多人認為React就是處理 **[MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)**架構中 **V** 的部份.
|
||||
|
||||
我們建造React用來解決一個問題: **開發資料能隨時間頻繁更新的大型應用程式**.
|
||||
|
||||
## 簡單(Simple)
|
||||
|
||||
簡單意味著你所開發的應用程式外觀任何一部分都要能即時呈現, 並且當資料有所變動時React能自動管理所有UI的更新.
|
||||
|
||||
## 陳述(Declarative)
|
||||
|
||||
當資料改變時, React概念上就像是點擊了 "刷新" 的按鈕, 並且知道只需更新有改變的部份.
|
||||
|
||||
## 建立可組合的元件(Composable Components)
|
||||
|
||||
React就是在建造可重用的元件(Components). 事實上, 當你使用React時 *唯一* 在做的事就是建立元件(Components). 由於它們封裝性高,元件使得程式碼能夠易於重複使用, 測試, 並且容易做到讓關注點分離(separation of concerns easy).
|
||||
|
||||
## 指引(Give It Five Minutes)
|
||||
|
||||
React挑戰了許多傳統的觀念, 第一次乍看之下這些構想可能看起來有點瘋狂. [Give it five minutes](https://signalvnoise.com/posts/3124-give-it-five-minutes) 而當閱讀完這篇指引; 這些瘋狂的構想在Facebook和Instagram裡裡外外建立了數以千計的元件(components)之後被證明是可實行的.
|
||||
|
||||
## 更多學習資源
|
||||
|
||||
從這裡你能學習到更多建造React背後的動機 [this blog post](/react/blog/2013/06/05/why-react.html).
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: displaying-data-it-IT
|
||||
title: Visualizzare Dati
|
||||
permalink: displaying-data-it-IT.html
|
||||
permalink: docs/displaying-data-it-IT.html
|
||||
prev: why-react-it-IT.html
|
||||
next: jsx-in-depth-it-IT.html
|
||||
---
|
||||
@@ -19,8 +19,9 @@ Diamo un'occhiata ad un esempio davvero semplice. Creiamo un file dal nome `hell
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: displaying-data-ja-JP
|
||||
title: データを表示する
|
||||
permalink: displaying-data-ja-JP.html
|
||||
permalink: docs/displaying-data-ja-JP.html
|
||||
prev: why-react-ja-JP.html
|
||||
next: jsx-in-depth-ja-JP.html
|
||||
|
||||
@@ -19,8 +19,9 @@ UIについて、最も基本的なことは、いくつかのデータを表示
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: displaying-data-ko-KR
|
||||
title: 데이터를 표시하기
|
||||
permalink: displaying-data-ko-KR.html
|
||||
permalink: docs/displaying-data-ko-KR.html
|
||||
prev: why-react-ko-KR.html
|
||||
next: jsx-in-depth-ko-KR.html
|
||||
---
|
||||
@@ -18,9 +18,9 @@ UI를 가지고 할 수 있는 가장 기초적인 것은 데이터를 표시하
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: displaying-data
|
||||
title: Displaying Data
|
||||
permalink: displaying-data.html
|
||||
permalink: docs/displaying-data.html
|
||||
prev: why-react.html
|
||||
next: jsx-in-depth.html
|
||||
---
|
||||
@@ -18,9 +18,9 @@ Let's look at a really simple example. Create a `hello-react.html` file with the
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
@@ -36,8 +36,8 @@ Let's look at a really simple example. Create a `hello-react.html` file with the
|
||||
For the rest of the documentation, we'll just focus on the JavaScript code and assume it's inserted into a template like the one above. Replace the placeholder comment above with the following JSX:
|
||||
|
||||
```javascript
|
||||
var HelloWorld = React.createClass({
|
||||
render: function() {
|
||||
class HelloWorld extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<p>
|
||||
Hello, <input type="text" placeholder="Your name here" />!
|
||||
@@ -45,14 +45,16 @@ var HelloWorld = React.createClass({
|
||||
</p>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setInterval(function() {
|
||||
function tick() {
|
||||
ReactDOM.render(
|
||||
<HelloWorld date={new Date()} />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
setInterval(tick, 500);
|
||||
```
|
||||
|
||||
## Reactive Updates
|
||||
|
||||
124
docs/docs/02-displaying-data.ru-RU.md
Normal file
124
docs/docs/02-displaying-data.ru-RU.md
Normal file
@@ -0,0 +1,124 @@
|
||||
---
|
||||
id: displaying-data-ru-RU
|
||||
title: Отображение данных
|
||||
permalink: docs/displaying-data-ru-RU.html
|
||||
prev: why-react-ru-RU.html
|
||||
next: jsx-in-depth.html
|
||||
---
|
||||
|
||||
Главная задача интерфейса — это отображать данные. React делает это легко и обновляет интерфейс сразу, как только изменятся данные.
|
||||
|
||||
## Начало
|
||||
|
||||
Давайте рассмотрим простой пример. Создайте файл `hello-react.html` со следующим текстом:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
<script type="text/babel">
|
||||
|
||||
// ** Ваш код будет здесь! **
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Добавим в этот шаблон немного JavaScript. Замените комментарий на следующий JSX-код:
|
||||
|
||||
```javascript
|
||||
var HelloWorld = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<p>
|
||||
Hello, <input type="text" placeholder="Your name here" />!
|
||||
It is {this.props.date.toTimeString()}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
setInterval(function() {
|
||||
ReactDOM.render(
|
||||
<HelloWorld date={new Date()} />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
}, 500);
|
||||
```
|
||||
|
||||
## Реактивные обновления
|
||||
|
||||
Откройте `hello-react.html` в браузере и введите в текстовое поле свое имя. Что происходит со страницей? Каждые полсекунды обновляется время, остальные же части страницы остаются без изменений. Обратите внимание, что мы не написали ни строчки кода, чтобы управлять этим поведением. React сам отлично понимает что надо делать и обновляет элементы на странице по мере необходимости.
|
||||
|
||||
Суть в том, что React не меняет DOM-дерево до тех пор, пока это не потребуется. **Чтобы отразить изменения, React использует быстрое внутреннее представление DOM-дерева и просчитывает как его изменить наиболее эффективно**.
|
||||
|
||||
Передаваемые в компонент данные называются `props` — сокращенно от "properties". В JSX коде они передаются как атрибуты компонента. Считайте, что компонент получает `props` только для чтения. **Никогда не перезаписывайте значения `this.props` внутри компонента.**
|
||||
|
||||
## Компоненты как функции
|
||||
|
||||
Компоненты React — довольно простые сущности. Можно считать их обыкновенными функциями, которые принимают на входе `props` и `state` (см. далее) и возвращают HTML. Если помнить об этом, то компоненты становятся простыми для понимания.
|
||||
|
||||
> Замечание:
|
||||
>
|
||||
> **Есть одно ограничение**: Компоненты React умеют возвращать только один узел. Если вам надо вернуть сразу несколько, они *должны* быть обернуты в один корневой узел.
|
||||
|
||||
## Синтаксис JSX
|
||||
|
||||
Мы убеждены, что компоненты — самый подходящий способ разделения ответственностей, гораздо более удобный чем "шаблоны" и "вынесение логики на страницу". Мы считаем, что разметка и код, который её генерирует, неотделимы друг от друга. Плюс, логика на странице часто бывает запутанной, и использование шаблонизаторов, чтобы описать её, только затрудняет работу.
|
||||
|
||||
Мы решили, что лучшим вариантом будет генерировать HTML и деревья компонентов прямо из JS кода. Так вы сможете зайдействовать всю выразительную мощь современного языка программирования для создания интерфейсов.
|
||||
|
||||
А чтобы упростить создание узлов дерева, мы ввели **опциональный** HTML-подобный синтаксис.
|
||||
|
||||
**JSX позволяет вам создавать JavaScript объекты используя синтаксис HTML**. Для генерации ссылки в React вы напишете на чистом JavaScript:
|
||||
|
||||
`React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')`
|
||||
|
||||
С JSX это станет:
|
||||
|
||||
`<a href="https://facebook.github.io/react/">Hello!</a>`
|
||||
|
||||
Мы установили, что с JSX создавать React приложения проще, и дизайнеров как правило устраивает его синтаксис. Но у разных людей разные предпочтения, поэтому стоит сказать, что **JSX необязателен при работе с React.**
|
||||
|
||||
JSX сам по себе очень прост. Чтобы узнать о нем больше, почитайте [подробно про JSX](/react/docs/jsx-in-depth.html). Или можете попробовать его в [Babel REPL](https://babeljs.io/repl/).
|
||||
|
||||
JSX похож на HTML, но но имеет существенные отличия. Почитайте про [подводные камни JSX](/react/docs/jsx-gotchas.html), чтобы понять их ключевые различия.
|
||||
|
||||
[Babel предлагает несколько способов начать работу с JSX](http://babeljs.io/docs/setup/), от консольных утилит до интеграций с Ruby on Rails. Выберите тот инструмент, который лучше всего вам подходит.
|
||||
|
||||
## React без использования JSX
|
||||
|
||||
JSX полностью опционален; вам совсем необязательно использовать его вместе с React. Вы можете создавать React-элементы на чистом JavaScript используя функцию `React.createElement`, которая принимает имя тега или компонента, объект со свойствами, и набор необязательных дочерних элементов.
|
||||
|
||||
```javascript
|
||||
var child1 = React.createElement('li', null, 'First Text Content');
|
||||
var child2 = React.createElement('li', null, 'Second Text Content');
|
||||
var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
|
||||
ReactDOM.render(root, document.getElementById('example'));
|
||||
```
|
||||
|
||||
Для удобства, вы можете создать сокращенные фабричные функции, чтобы создавать React-элементы из ваших собственных компонентов.
|
||||
|
||||
```javascript
|
||||
var Factory = React.createFactory(ComponentClass);
|
||||
...
|
||||
var root = Factory({ custom: 'prop' });
|
||||
ReactDOM.render(root, document.getElementById('example'));
|
||||
```
|
||||
|
||||
А для базовых HTML тегов в React уже есть встроенные фабрики:
|
||||
|
||||
```javascript
|
||||
var root = React.DOM.ul({ className: 'my-list' },
|
||||
React.DOM.li(null, 'Text Content')
|
||||
);
|
||||
```
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: displaying-data-zh-CN
|
||||
title: 显示数据
|
||||
permalink: displaying-data-zh-CN.html
|
||||
permalink: docs/displaying-data-zh-CN.html
|
||||
prev: why-react-zh-CN.html
|
||||
next: jsx-in-depth-zh-CN.html
|
||||
---
|
||||
@@ -18,9 +18,9 @@ next: jsx-in-depth-zh-CN.html
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
125
docs/docs/02-displaying-data.zh-TW.md
Normal file
125
docs/docs/02-displaying-data.zh-TW.md
Normal file
@@ -0,0 +1,125 @@
|
||||
---
|
||||
id: displaying-data-zh-TW
|
||||
title: Displaying Data
|
||||
permalink: docs/displaying-data-zh-TW.html
|
||||
prev: why-react-zh-TW.html
|
||||
next: jsx-in-depth-zh-TW.html
|
||||
---
|
||||
|
||||
在使用者介面所能做最基本的事情就是呈現資料. React讓呈現資料變得更加容易並且當資料有所變動時也能自動地讓使用者介面保持呈現最新的資料.
|
||||
|
||||
## 入門(Getting Started)
|
||||
|
||||
我們從一個相當簡單的範例開始. 建立一個名為 `hello-react.html` 的檔案裡面包含下列程式碼:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
<script type="text/babel">
|
||||
|
||||
// ** 將你的程式碼放在這裡! **
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
這份文件其他部份,我們將只會專注在JavaScript程式碼解說上,並且假設程式碼會被放置在如上述模板的註解區塊內. 用下列的JSX程式碼取代上述註解區塊:
|
||||
|
||||
```javascript
|
||||
var HelloWorld = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<p>
|
||||
Hello, <input type="text" placeholder="Your name here" />!
|
||||
It is {this.props.date.toTimeString()}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
setInterval(function() {
|
||||
ReactDOM.render(
|
||||
<HelloWorld date={new Date()} />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
}, 500);
|
||||
```
|
||||
|
||||
## 反應性更新(Reactive Updates)
|
||||
|
||||
在一個瀏覽器上開啟檔案 `hello-react.html` 並且在文字區塊填入你的名字. 請注意React僅僅改變UI上的時間字串 — 你在文字區塊輸入的任何文字依舊存在, 即使你並沒有寫任何程式碼來管理這個行為.React可以為你分辨出這樣的行為並且做出正確的回應.
|
||||
|
||||
之所以能夠分辨出這樣的行為是因為React除非在真正有必要的情況下,否則不會對DOM做任何操作. **它使用一個快速的, 內部虛擬的DOM(internal mock DOM)來為你施行比較和計算最有效率的DOM變動(DOM mutation)**
|
||||
|
||||
輸入到元件(component)的內容我們稱為`props` — 是屬性("properties")的簡稱. 他們在JSX語法中作為傳遞屬性之用. 你應該把這些屬性當做元件中不可被改變的, 也就是說, **永遠不要對 `this.props` 做寫入的行為**.
|
||||
|
||||
## 元件就是函數(Components are Just Like Functions)
|
||||
|
||||
React元件(components)是非常簡單的. 你能把它們想成是簡單的函數帶入`props`和`state`(後面會討論這部份)並且呈送給HTML(render HTML). 在心中保持住這個想法, 就能容易理解元件(components).
|
||||
React components are very simple. You can think of them as simple functions that take in `props` and `state` (discussed later) and render HTML. With this in mind, components are easy to reason about.
|
||||
|
||||
> 注意(Note):
|
||||
>
|
||||
> **一個局限性**: React元件(components)只能呈送(render)給一個單一根節點(root node). 如果你想要回傳多個節點(multiple nodes)他們*必須*被包裹在單一根節點內.
|
||||
|
||||
## JSX語法
|
||||
|
||||
我們深信元件(components)才是分離關注點(separate concerns)的正確方法, 而並非傳統的模板("templates")和顯示邏輯("display logic")觀念. 我們認為標記(markup)和產生它的程式碼應當緊密的綁在一起. 另外, 顯示邏輯(display logic)常常是非常複雜的, 若使用模板語言(template languages)來詮釋它就顯得笨重或累贅.
|
||||
|
||||
我們找到解決這個問題的最佳解答就是直接在JavaScript程式內產生HTML和元件樹(component trees)如此一來你就能使用真正的程式語言的表達能力(expressive power)來建立使用者介面(UIs).
|
||||
|
||||
為了能更輕鬆實現, 我們增加了一個非常簡單, **可選擇性使用的** 類似HTML的語法(HTML-like syntax) 來創建這些React樹節點(React tree nodes).
|
||||
|
||||
**JSX能讓你使用HTML語法來創建JavaScript物件.** 在React裡使用純JavaScript來產生一個鏈接(link)你可以這樣寫:
|
||||
|
||||
`React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')`
|
||||
|
||||
使用JSX語法則變成:
|
||||
|
||||
`<a href="https://facebook.github.io/react/">Hello!</a>`
|
||||
|
||||
我們發現這麼做能讓建立React apps更加容易並且設計師往往喜歡語法, 但是每個人都有他們自己的工作流程, 所以**在使用React時JSX並非必要.**
|
||||
|
||||
JSX非常簡單易懂. 若想要學習更多關於JSX, 請參閱 [JSX in depth](/react/docs/jsx-in-depth.html). 或是可以使用線上及時轉換工具 [the Babel REPL](https://babeljs.io/repl/).
|
||||
|
||||
JSX類似於HTML, 但不盡然完全相同. 參閱 [JSX gotchas](/react/docs/jsx-gotchas.html) 來比較一些主要的差異點.
|
||||
|
||||
[Babel exposes a number of ways to get started using JSX](http://babeljs.io/docs/setup/), 涵蓋從命令列工具到Ruby on Rails整合. 可以從中選擇最適合你的工具.
|
||||
|
||||
## React不使用JSX的範例(React without JSX)
|
||||
|
||||
JSX完全是可選擇性使用的; 你可以不拿JSX跟React一起使用. 你能在純粹的JavaScript環境中使用`React.createElement`來創建React元素(React elements), 它搭配一個標籤名(tag name)或是元件(component), 一個屬性物件(properties object), 和數個選擇性子參數(child arguments).
|
||||
|
||||
```javascript
|
||||
var child1 = React.createElement('li', null, 'First Text Content');
|
||||
var child2 = React.createElement('li', null, 'Second Text Content');
|
||||
var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
|
||||
ReactDOM.render(root, document.getElementById('example'));
|
||||
```
|
||||
|
||||
為了方便起見, 你能創建速記factory函式(short-hand factory functions)然後從自訂元件(custom components)建立元素(elements).
|
||||
|
||||
```javascript
|
||||
var Factory = React.createFactory(ComponentClass);
|
||||
...
|
||||
var root = Factory({ custom: 'prop' });
|
||||
ReactDOM.render(root, document.getElementById('example'));
|
||||
```
|
||||
|
||||
針對一般的HTML標籤React已經有內建的factories函式:
|
||||
|
||||
```javascript
|
||||
var root = React.DOM.ul({ className: 'my-list' },
|
||||
React.DOM.li(null, 'Text Content')
|
||||
);
|
||||
```
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-in-depth-it-IT
|
||||
title: JSX in Profondità
|
||||
permalink: jsx-in-depth-it-IT.html
|
||||
permalink: docs/jsx-in-depth-it-IT.html
|
||||
prev: displaying-data-it-IT.html
|
||||
next: jsx-spread-it-IT.html
|
||||
---
|
||||
@@ -84,7 +84,7 @@ var Nav = React.createClass({displayName: "Nav", });
|
||||
|
||||
Usa la [REPL di Babel](https://babeljs.io/repl/) per provare il JSX e vedere come viene trasformato
|
||||
in JavaScript nativo, e il
|
||||
[convertitore da HTML a JSX](/react/html-jsx.html) per convertire il tuo HTML esistente a
|
||||
[convertitore da HTML a JSX](http://magic.reactjs.net/htmltojsx.htm) per convertire il tuo HTML esistente a
|
||||
JSX.
|
||||
|
||||
Se desideri utilizzare JSX, la guida [Primi Passi](/react/docs/getting-started-it-IT.html) ti mostra come impostare la compilazione.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-in-depth
|
||||
title: JSXの深層
|
||||
permalink: jsx-in-depth-ja-JP.html
|
||||
permalink: docs/jsx-in-depth-ja-JP.html
|
||||
prev: displaying-data-ja-JP.html
|
||||
next: jsx-spread-ja_JP.html
|
||||
---
|
||||
@@ -80,7 +80,7 @@ var Nav = React.createClass({ });
|
||||
var Nav = React.createClass({displayName: "Nav", });
|
||||
```
|
||||
|
||||
JSXを試し、どのようにネイティブなJavaScriptに変換されるか見るには、[JSX Compiler](/react/jsx-compiler.html)を、すでに存在するHTMLをJSXに変換するには[HTMLからJSXへのコンバーター](/react/html-jsx.html)を使ってください。
|
||||
JSXを試し、どのようにネイティブなJavaScriptに変換されるか見るには、[JSX Compiler](/react/jsx-compiler.html)を、すでに存在するHTMLをJSXに変換するには[HTMLからJSXへのコンバーター](http://magic.reactjs.net/htmltojsx.htm)を使ってください。
|
||||
|
||||
JSXを使いたい場合は、[始めてみましょう](/react/docs/getting-started-ja-JP.html)というガイドがどのようにコンパイルを設定するか示してくれます。
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-in-depth-ko-KR
|
||||
title: JSX 깊이보기
|
||||
permalink: jsx-in-depth-ko-KR.html
|
||||
permalink: docs/jsx-in-depth-ko-KR.html
|
||||
prev: displaying-data-ko-KR.html
|
||||
next: jsx-spread-ko-KR.html
|
||||
---
|
||||
@@ -45,7 +45,6 @@ React JSX는 대소문자를 로컬 컴포넌트 클래스와 HTML 태그를 구
|
||||
> 권장하지 않습니다. 대신, React DOM 컴포넌트는 각각 `className`, `htmlFor`같은
|
||||
> DOM 프로퍼티 이름을 기대합니다.
|
||||
|
||||
<a name="the-transform"></a>
|
||||
## 변환
|
||||
|
||||
React JSX는 XML같은 문법에서 네이티브 JavaScript로 변환됩니다. XML 엘리먼트, 어트리뷰트, 자식은 `React.createElement`에 넘겨지는 인자로 변환됩니다.
|
||||
@@ -74,7 +73,7 @@ var app = React.createElement(
|
||||
);
|
||||
```
|
||||
|
||||
클래스에 [displayName](/react/docs/component-specs-ko-KR.html#displayName)이 정의되어 있지 않으면 JSX는 변수명을 displayName으로 간주할 것입니다:
|
||||
클래스에 [displayName](/react/docs/component-specs-ko-KR.html#displayname)이 정의되어 있지 않으면 JSX는 변수명을 displayName으로 간주할 것입니다:
|
||||
|
||||
```javascript
|
||||
// 입력 (JSX):
|
||||
@@ -83,7 +82,7 @@ var Nav = React.createClass({ });
|
||||
var Nav = React.createClass({displayName: "Nav", });
|
||||
```
|
||||
|
||||
[바벨 REPL](https://babeljs.io/repl/)를 보면 JSX에서 어떻게 네이티브 JavaScript로 변환(desugars)하는지 볼 수 있고, [HTML-JSX 변환기](/react/html-jsx.html)는 이미 있는 HTML을 JSX로 변환해 줍니다.
|
||||
[바벨 REPL](https://babeljs.io/repl/)를 보면 JSX에서 어떻게 네이티브 JavaScript로 변환(desugars)하는지 볼 수 있고, [HTML-JSX 변환기](http://magic.reactjs.net/htmltojsx.htm)는 이미 있는 HTML을 JSX로 변환해 줍니다.
|
||||
|
||||
JSX를 사용 하시려면, [시작하기](/react/docs/getting-started-ko-KR.html) 가이드에서 어떻게 컴파일을 하기 위해 설정하는지 보실 수 있습니다.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-in-depth
|
||||
title: JSX in Depth
|
||||
permalink: jsx-in-depth.html
|
||||
permalink: docs/jsx-in-depth.html
|
||||
prev: displaying-data.html
|
||||
next: jsx-spread.html
|
||||
---
|
||||
@@ -82,7 +82,7 @@ var Nav = React.createClass({ });
|
||||
var Nav = React.createClass({displayName: "Nav", });
|
||||
```
|
||||
|
||||
Use the [Babel REPL](https://babeljs.io/repl/) to try out JSX and see how it desugars into native JavaScript, and the [HTML to JSX converter](/react/html-jsx.html) to convert your existing HTML to JSX.
|
||||
Use the [Babel REPL](https://babeljs.io/repl/) to try out JSX and see how it desugars into native JavaScript, and the [HTML to JSX converter](http://magic.reactjs.net/htmltojsx.htm) to convert your existing HTML to JSX.
|
||||
|
||||
If you want to use JSX, the [Getting Started](/react/docs/getting-started.html) guide shows how to set up compilation.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-in-depth-zh-CN
|
||||
title: 深入 JSX
|
||||
permalink: jsx-in-depth-zh-CN.html
|
||||
permalink: docs/jsx-in-depth-zh-CN.html
|
||||
prev: displaying-data-zh-CN.html
|
||||
next: jsx-spread-zh-CN.html
|
||||
---
|
||||
@@ -82,7 +82,7 @@ var Nav = React.createClass({ });
|
||||
var Nav = React.createClass({displayName: "Nav", });
|
||||
```
|
||||
|
||||
使用 [JSX 编译器](/react/jsx-compiler.html) 来试用 JSX 并理解它是如何转换到原生 JavaScript,还有 [HTML 到 JSX 转换器](/react/html-jsx.html) 来把现有 HTML 转成 JSX。
|
||||
使用 [JSX 编译器](/react/jsx-compiler.html) 来试用 JSX 并理解它是如何转换到原生 JavaScript,还有 [HTML 到 JSX 转换器](http://magic.reactjs.net/htmltojsx.htm) 来把现有 HTML 转成 JSX。
|
||||
|
||||
如果你要使用 JSX,这篇 [新手入门](/react/docs/getting-started.html) 教程来教你如何搭建环境。
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-spread-it-IT
|
||||
title: Attributi Spread JSX
|
||||
permalink: jsx-spread-it-IT.html
|
||||
permalink: docs/jsx-spread-it-IT.html
|
||||
prev: jsx-in-depth-it-IT.html
|
||||
next: jsx-gotchas-it-IT.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-spread
|
||||
title: JSXの拡張属性
|
||||
permalink: jsx-spread-ja-JP.html
|
||||
permalink: docs/jsx-spread-ja-JP.html
|
||||
prev: jsx-in-depth-ja-JP.html
|
||||
next: jsx-gotchas-ja-JP.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-spread-ko-KR
|
||||
title: JSX 스프레드 어트리뷰트
|
||||
permalink: jsx-spread-ko-KR.html
|
||||
permalink: docs/jsx-spread-ko-KR.html
|
||||
prev: jsx-in-depth-ko-KR.html
|
||||
next: jsx-gotchas-ko-KR.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-spread
|
||||
title: JSX Spread Attributes
|
||||
permalink: jsx-spread.html
|
||||
permalink: docs/jsx-spread.html
|
||||
prev: jsx-in-depth.html
|
||||
next: jsx-gotchas.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-spread-zh-CN
|
||||
title: JSX 展开属性
|
||||
permalink: jsx-spread-zh-CN.html
|
||||
permalink: docs/jsx-spread-zh-CN.html
|
||||
prev: jsx-in-depth-zh-CN.html
|
||||
next: jsx-gotchas-zh-CN.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-gotchas-it-IT
|
||||
title: JSX Gotchas
|
||||
permalink: jsx-gotchas-it-IT.html
|
||||
permalink: docs/jsx-gotchas-it-IT.html
|
||||
prev: jsx-spread-it-IT.html
|
||||
next: interactivity-and-dynamic-uis-it-IT.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-gotchas
|
||||
title: JSXの理解
|
||||
permalink: jsx-gotchas-ja-JP.html
|
||||
permalink: docs/jsx-gotchas-ja-JP.html
|
||||
prev: jsx-spread-ja-JP.html
|
||||
next: interactivity-and-dynamic-uis-ja-JP.html
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-gotchas-ko-KR
|
||||
title: JSX Gotchas
|
||||
permalink: jsx-gotchas-ko-KR.html
|
||||
permalink: docs/jsx-gotchas-ko-KR.html
|
||||
prev: jsx-spread-ko-KR.html
|
||||
next: interactivity-and-dynamic-uis-ko-KR.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-gotchas
|
||||
title: JSX Gotchas
|
||||
permalink: jsx-gotchas.html
|
||||
permalink: docs/jsx-gotchas.html
|
||||
prev: jsx-spread.html
|
||||
next: interactivity-and-dynamic-uis.html
|
||||
---
|
||||
@@ -40,10 +40,10 @@ A safer alternative is to find the [unicode number corresponding to the entity](
|
||||
<div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
|
||||
```
|
||||
|
||||
You can use mixed arrays with strings and JSX elements.
|
||||
You can use mixed arrays with strings and JSX elements. Each JSX element in the array needs a unique key.
|
||||
|
||||
```javascript
|
||||
<div>{['First ', <span>·</span>, ' Second']}</div>
|
||||
<div>{['First ', <span key="middot">·</span>, ' Second']}</div>
|
||||
```
|
||||
|
||||
As a last resort, you always have the ability to [insert raw HTML](/react/tips/dangerously-set-inner-html.html).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: jsx-gotchas-zh-CN
|
||||
title: JSX 陷阱
|
||||
permalink: jsx-gotchas-zh-CN.html
|
||||
permalink: docs/jsx-gotchas-zh-CN.html
|
||||
prev: jsx-spread-zh-CN.html
|
||||
next: interactivity-and-dynamic-uis-zh-CN.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: interactivity-and-dynamic-uis-it-IT
|
||||
title: Interattività e UI Dinamiche
|
||||
permalink: interactivity-and-dynamic-uis-it-IT.html
|
||||
permalink: docs/interactivity-and-dynamic-uis-it-IT.html
|
||||
prev: jsx-gotchas-it-IT.html
|
||||
next: multiple-components-it-IT.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: interactivity-and-dynamic-uis
|
||||
title: 相互作用と動的なUI
|
||||
permalink: interactivity-and-dynamic-uis-ja-JP.html
|
||||
permalink: docs/interactivity-and-dynamic-uis-ja-JP.html
|
||||
prev: jsx-gotchas-ja-JP.html
|
||||
next: multiple-components-ja-JP.html
|
||||
---
|
||||
@@ -20,7 +20,7 @@ var LikeButton = React.createClass({
|
||||
this.setState({liked: !this.state.liked});
|
||||
},
|
||||
render: function() {
|
||||
var text = this.state.liked ? 'like' : 'haven\'t liked';
|
||||
var text = this.state.liked ? 'liked' : 'haven\'t liked';
|
||||
return (
|
||||
<p onClick={this.handleClick}>
|
||||
You {text} this. Click to toggle.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: interactivity-and-dynamic-uis-ko-KR
|
||||
title: 상호 작용 및 동적 UI
|
||||
permalink: interactivity-and-dynamic-uis-ko-KR.html
|
||||
permalink: docs/interactivity-and-dynamic-uis-ko-KR.html
|
||||
prev: jsx-gotchas-ko-KR.html
|
||||
next: multiple-components-ko-KR.html
|
||||
---
|
||||
@@ -19,7 +19,7 @@ var LikeButton = React.createClass({
|
||||
this.setState({liked: !this.state.liked});
|
||||
},
|
||||
render: function() {
|
||||
var text = this.state.liked ? 'like' : 'haven\'t liked';
|
||||
var text = this.state.liked ? 'liked' : 'haven\'t liked';
|
||||
return (
|
||||
<p onClick={this.handleClick}>
|
||||
You {text} this. Click to toggle.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: interactivity-and-dynamic-uis
|
||||
title: Interactivity and Dynamic UIs
|
||||
permalink: interactivity-and-dynamic-uis.html
|
||||
permalink: docs/interactivity-and-dynamic-uis.html
|
||||
prev: jsx-gotchas.html
|
||||
next: multiple-components.html
|
||||
---
|
||||
@@ -11,22 +11,26 @@ You've already [learned how to display data](/react/docs/displaying-data.html) w
|
||||
## A Simple Example
|
||||
|
||||
```javascript
|
||||
var LikeButton = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {liked: false};
|
||||
},
|
||||
handleClick: function(event) {
|
||||
class LikeButton extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
liked: false
|
||||
};
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
handleClick() {
|
||||
this.setState({liked: !this.state.liked});
|
||||
},
|
||||
render: function() {
|
||||
var text = this.state.liked ? 'like' : 'haven\'t liked';
|
||||
}
|
||||
render() {
|
||||
const text = this.state.liked ? 'liked' : 'haven\'t liked';
|
||||
return (
|
||||
<p onClick={this.handleClick}>
|
||||
<div onClick={this.handleClick}>
|
||||
You {text} this. Click to toggle.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<LikeButton />,
|
||||
|
||||
78
docs/docs/03-interactivity-and-dynamic-uis.ru-RU.md
Normal file
78
docs/docs/03-interactivity-and-dynamic-uis.ru-RU.md
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
id: interactivity-and-dynamic-uis-ru-RU
|
||||
title: Интерактивные и динамические интерфейсы
|
||||
permalink: docs/interactivity-and-dynamic-uis-ru-RU.html
|
||||
prev: jsx-gotchas.html
|
||||
next: multiple-components.html
|
||||
---
|
||||
|
||||
Вы уже знаете [как показывать данные](/react/docs/displaying-data.html) с React. Теперь давайте добавим в наши интферфейсы немного интерактивности.
|
||||
|
||||
## Простой пример
|
||||
|
||||
```javascript
|
||||
var LikeButton = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {liked: false};
|
||||
},
|
||||
handleClick: function(event) {
|
||||
this.setState({liked: !this.state.liked});
|
||||
},
|
||||
render: function() {
|
||||
var text = this.state.liked ? 'liked' : 'haven\'t liked';
|
||||
return (
|
||||
<p onClick={this.handleClick}>
|
||||
You {text} this. Click to toggle.
|
||||
</p>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<LikeButton />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
## Обработка событий и синтетические события
|
||||
|
||||
С React вы просто передаете функцию-обработчик нужного события как аргумент, почти так же, как делали это в HTML. Благодаря механизму синтетических событий React гарантирует, что все события будут вести себя одинаково во всех браузерах. Другими словами, React знает, как работает всплытие и перехват событий по спецификации. События, которые он передает в ваши обработчики, будут соответствовать [спецификации W3C](http://www.w3.org/TR/DOM-Level-3-Events/), несмотря на то, каким браузером вы пользуетесь.
|
||||
|
||||
## Как это работает: автоматическое связывание и делегирование событий
|
||||
|
||||
Чтобы ваш код был не только понятным, но и быстрым, React делает следующее:
|
||||
|
||||
**Автоматическое связывание:** Когда в JavaScript создаются функции обратного вызова, вам надо привязать метод к тому объекту, на котором он будет вызываться, чтобы значение `this` было корректным. С React привязка метода к компоненту происходит автоматически ([кроме тех случаев, когда вы используете классы ES6](/react/docs/reusable-components.html#no-autobinding)). И делается это с минимальной нагрузкой на процессор и память.
|
||||
|
||||
**Делегирование событий:** На самом же деле, React добавляет обработчики событий не к узлам дерева. Сразу после запуска, React начинает прослушивать все события с самого верхнего уровня, используя единый слушатель. Когда добавляется новый компонент или удаляется старый, обработчики событий просто добавляются или удаляются из памяти React. И когда событие наступает, React уже заранее знает какому из обработчиков его передать. Когда в памяти больше не остается обработчиков, React перестает обрабатывать события. Если хотите узнать о том, почему эта механика так быстро работает, почитайте [отличный пост в блоге David Walsh](http://davidwalsh.name/event-delegate).
|
||||
|
||||
## Компоненты как конечные автоматы
|
||||
|
||||
React считает интерфейсы обыкновенными конечными автоматами. Работать с интерфейсом становится проще, если представлять его как конечный автомат, который меняет состояния и отрисовывает их.
|
||||
|
||||
В React вы просто обновляете состояние компонента, а потом выводите новый интерфейс уже с новыми данными. Все изменения в DOM-дереве React сделает сам, причем наиболее эффективным способом.
|
||||
|
||||
## Как работает состояние
|
||||
|
||||
Чтобы сообщить React о том, что данные изменились, вы вызываете метод `setState(data, callback)`. В этом методе происходит обновление состояния `this.state` новыми данными из `data`, и компонент отрисуется заново. После этого вызывается функция `callback`. Но вы редко будете ей пользоваться, ведь React сам обновляет интерфейс.
|
||||
|
||||
## В каких компонентах хранить состояние?
|
||||
|
||||
Большинство компонентов должны просто брать данные из `props` и отрисовывать их. Но иногда вам надо реагировать на действия пользователя, делать запросы на сервер или просто сделать что-то по таймеру. В таких случаях используйте состояние.
|
||||
|
||||
**Старайтесь делать компоненты без состояния.** Следуя этому правилу, вы будете выносить работу с состоянием с уровня представления в другие, более подходящие места. Тем самым, вы снизите сложность приложения, упрощая его понимание.
|
||||
|
||||
Основной принцип такой: создаются несколько компонентов без состояния, которые формируют дерево. Они будут заниматься только отрисовкой данных. А все данные для них будут у родительского компонента, который будет на вершине этого дерева компонентов. Он и будет передавать данные дочерним узлам через `props`. Этот компонент с общим состоянием содержит в себе всю логику взаимодействия, а дочерние компоненты будут только отрисовывать данные, которые будут у них в `props`.
|
||||
|
||||
## Какие данные *надо* помещать в состояние?
|
||||
|
||||
**Состояние должно содержать данные, которые нужны для обновления интерфейса.** В реальных приложениях такие данные, как правило, незначительны по объему, и могут быть сериализованы в JSON. Когда вы создаете компонент с состоянием, старайтесь поместить в него минимум данных. А уже внутри метода `render()` вычисляйте остальные данные, используя значения из состояния.
|
||||
Со временем вы увидите, что такой подход позволяет создавать более стройные и устойчивые к изменениям приложения. Добавление в состояние лишних данных требует от вас дополнительных затрат на их синхронизацию. Но этого можно избежать, если позволить React делать все эти вычисления за вас.
|
||||
|
||||
## Какие данные *не надо* помещать в состояние?
|
||||
|
||||
Состояние `this.state` должно содержать минимум данных, необходимых для отображения интерфейса. Поэтому не стоит хранить в нем:
|
||||
|
||||
* **Вычисляемые данные:** Не волнуйтесь о данных, которые можно вычислить из состояния. Согласованность данных проще обеспечить, если производить все вычисления в методе `render()`. Например, если в состоянии хранится список элементов, и вам надо вывести его размер в виде строки, напишите `this.state.listItems.length + ' элементов'` в методе `render()`. Это будет правильнее, чем хранить размер списка в состоянии.
|
||||
* **Компоненты React:** Создавайте их в методе `render()`, опираясь на данные из `props` и `state`.
|
||||
* **Значения, повторяющие `props`:** Старайтесь по мере возможности использовать `props` как единственный источник данных. Хранить значения `props` в состоянии допускается, только если вам надо где-то хранить их прошлые значения, ведь `props` могут измениться после отрисовки родительского компонента.
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: interactivity-and-dynamic-uis-zh-CN
|
||||
title: 动态交互式用户界面
|
||||
permalink: interactivity-and-dynamic-uis-zh-CN.html
|
||||
permalink: docs/interactivity-and-dynamic-uis-zh-CN.html
|
||||
prev: jsx-gotchas-zh-CN.html
|
||||
next: multiple-components-zh-CN.html
|
||||
---
|
||||
@@ -19,7 +19,7 @@ var LikeButton = React.createClass({
|
||||
this.setState({liked: !this.state.liked});
|
||||
},
|
||||
render: function() {
|
||||
var text = this.state.liked ? 'like' : 'haven\'t liked';
|
||||
var text = this.state.liked ? 'liked' : 'haven\'t liked';
|
||||
return (
|
||||
<p onClick={this.handleClick}>
|
||||
You {text} this. Click to toggle.
|
||||
@@ -42,9 +42,9 @@ React 里只需把事件处理器(event handler)以骆峰命名(camelCased
|
||||
|
||||
在幕后,React 做了一些操作来让代码高效运行且易于理解。
|
||||
|
||||
**Autobinding:** 在 JavaScript 里创建回调的时候,为了保证 `this` 的正确性,一般都需要显式地绑定方法到它的实例上。在 React,所有方法被自动绑定到了它的组件实例上(除非使用ES6的class符号)。React 还缓存这些绑定方法,所以 CPU 和内存都是非常高效。而且还能减少打字!
|
||||
**自动绑定:** 在 JavaScript 里创建回调的时候,为了保证 `this` 的正确性,一般都需要显式地绑定方法到它的实例上。在 React 中,所有方法被自动绑定到了它的组件实例上([除非使用ES6的class符号](/react/docs/reusable-components.html#no-autobinding))。React 还缓存这些绑定方法,所以 CPU 和内存都是非常高效。而且还能减少打字!
|
||||
|
||||
**事件代理 :** React 实际并没有把事件处理器绑定到节点本身。当 React 启动的时候,它在最外层使用唯一一个事件监听器处理所有事件。当组件被加载和卸载时,只是在内部映射里添加或删除事件处理器。当事件触发,React 根据映射来决定如何分发。当映射里处理器时,会当作空操作处理。参考 [David Walsh 很棒的文章](http://davidwalsh.name/event-delegate) 了解这样做高效的原因。
|
||||
**事件代理:** React 实际并没有把事件处理器绑定到节点本身。当 React 启动的时候,它在最外层使用唯一一个事件监听器处理所有事件。当组件被加载和卸载时,只是在内部映射里添加或删除事件处理器。当事件触发,React 根据映射来决定如何分发。当映射里没有事件处理函数时,会当作空操作处理。参考 [David Walsh 很棒的文章](http://davidwalsh.name/event-delegate) 了解这样做高效的原因。
|
||||
|
||||
## 组件其实是状态机(State Machines)
|
||||
|
||||
@@ -54,24 +54,24 @@ React 里,只需更新组件的 state,然后根据新的 state 重新渲染
|
||||
|
||||
## State 工作原理
|
||||
|
||||
常用的通知 React 数据变化的方法是调用 `setState(data, callback)`。这个方法会合并(merge) `data` 到 `this.state`,并重新渲染组件。渲染完成后,调用可选的 `callback` 回调。大部分情况下不需要提供 `callback`,因为 React 会负责把界面更新到最新状态。
|
||||
常用的通知 React 数据变化的方法是调用 `setState(data, callback)`。这个方法会合并(merge) `data` 到 `this.state`,并重新渲染组件。重新渲染完成后,调用可选的 `callback` 回调。大部分情况下不需要提供 `callback`,因为 React 会负责把界面更新到最新状态。
|
||||
|
||||
## 哪些组件应该有 State?
|
||||
|
||||
大部分组件的工作应该是从 `props` 里取数据并渲染出来。但是,有时需要对用户输入、服务器请求或者时间变化等作出响应,这时才需要使用 State。
|
||||
|
||||
** 尝试把尽可能多的组件无状态化。** 这样做能隔离 state,把它放到最合理的地方,也能减少冗余并,同时易于解释程序运作过程。
|
||||
**尝试把尽可能多的组件无状态化。** 这样做能隔离 state,把它放到最合理的地方,也能减少冗余,同时易于解释程序运作过程。
|
||||
|
||||
常用的模式是创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 `props` 传给子级。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。
|
||||
|
||||
## 哪些 *应该* 作为 State?
|
||||
|
||||
**State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。** 真实的应用中这种数据一般都很小且能被 JSON 序列化。当创建一个状态化的组件时,想象一下表示它的状态最少需要哪些数据,并只把这些数据存入 `this.state`。在 `render()` 里再根据 state 来计算你需要的其它数据。你会发现以这种方式思考和开发程序最终往往是正确的,因为如果在 state 里添加冗余数据或计算所得数据,需要你经常手动保持数据同步,不能让 React 来帮你处理。
|
||||
**State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。** 真实的应用中这种数据一般都很小且能被 JSON 序列化。当创建一个状态化的组件时,思考一下表示它的状态最少需要哪些数据,并只把这些数据存入 `this.state`。在 `render()` 里再根据 state 来计算你需要的其它数据。你会发现以这种方式思考和开发程序最终往往是正确的,因为如果在 state 里添加冗余数据或计算所得数据,那么你就需要经常手动保持数据同步,而不能让 React 来帮你处理。
|
||||
|
||||
## 哪些 *不应该* 作为 State?
|
||||
|
||||
`this.state` 应该仅包括能表示用户界面状态所需的最少数据。因些,它不应该包括:
|
||||
`this.state` 应该仅包括能表示用户界面状态所需的最少数据。因此,它不应该包括:
|
||||
|
||||
* **计算所得数据:** 不要担心根据 state 来预先计算数据 —— 把所有的计算都放到 `render()` 里更容易保证用户界面和数据的一致性。例如,在 state 里有一个数组(listItems),我们要把数组长度渲染成字符串, 直接在 `render()` 里使用 `this.state.listItems.length + ' list items'` 比把它放到 state 里好的多。
|
||||
* **React 组件:** 在 `render()` 里使用当前 props 和 state 来创建它。
|
||||
* **基于 props 的重复数据:** 尽可能使用 props 来作为实际状态的源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为 props 可能因为父组件重绘的结果而变化。
|
||||
* **基于 props 的重复数据:** 尽可能使用 props 来作为实际状态的源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为 props 可能因为父组件的重绘而变化。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: multiple-components-it-IT
|
||||
title: Componenti Multipli
|
||||
permalink: multiple-components-it-IT.html
|
||||
permalink: docs/multiple-components-it-IT.html
|
||||
prev: interactivity-and-dynamic-uis-it-IT.html
|
||||
next: reusable-components-it-IT.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: multiple-components
|
||||
title: 複数のコンポーネント
|
||||
permalink: multiple-components-ja-JP.html
|
||||
permalink: docs/multiple-components-ja-JP.html
|
||||
prev: interactivity-and-dynamic-uis-ja-JP.html
|
||||
next: reusable-components-ja-JP.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: multiple-components-ko-KR
|
||||
title: 복합 컴포넌트
|
||||
permalink: multiple-components-ko-KR.html
|
||||
permalink: docs/multiple-components-ko-KR.html
|
||||
prev: interactivity-and-dynamic-uis-ko-KR.html
|
||||
next: reusable-components-ko-KR.html
|
||||
---
|
||||
@@ -105,7 +105,6 @@ React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트
|
||||
</Card>
|
||||
```
|
||||
|
||||
<a name="dynamic-children"></a>
|
||||
### 동적 자식
|
||||
|
||||
자식들이 섞이거나(검색의 결과같은 경우) 새로운 컴포넌트가 목록의 앞에 추가(스트림같은 경우)된다면 상황은 점점 더 까다로워집니다. 이런 때에의 동일성과 각 자식의 상태는 반드시 렌더 패스 간에 유지돼야 합니다. 각 자식에 `key`를 할당 함으로써 독자적으로 식별할 수 있습니다.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: multiple-components
|
||||
title: Multiple Components
|
||||
permalink: multiple-components.html
|
||||
permalink: docs/multiple-components.html
|
||||
prev: interactivity-and-dynamic-uis.html
|
||||
next: reusable-components.html
|
||||
---
|
||||
@@ -17,8 +17,8 @@ By building modular components that reuse other components with well-defined int
|
||||
Let's create a simple Avatar component which shows a Facebook page picture and name using the Facebook Graph API.
|
||||
|
||||
```javascript
|
||||
var Avatar = React.createClass({
|
||||
render: function() {
|
||||
class Avatar extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PagePic pagename={this.props.pagename} />
|
||||
@@ -26,25 +26,25 @@ var Avatar = React.createClass({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var PagePic = React.createClass({
|
||||
render: function() {
|
||||
class PagePic extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<img src={'https://graph.facebook.com/' + this.props.pagename + '/picture'} />
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var PageLink = React.createClass({
|
||||
render: function() {
|
||||
class PageLink extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<a href={'https://www.facebook.com/' + this.props.pagename}>
|
||||
{this.props.pagename}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<Avatar pagename="Engineering" />,
|
||||
@@ -110,13 +110,12 @@ In most cases, this can be sidestepped by hiding elements instead of destroying
|
||||
The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a `key`:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
var results = this.props.results;
|
||||
render() {
|
||||
return (
|
||||
<ol>
|
||||
{results.map(function(result) {
|
||||
return <li key={result.id}>{result.text}</li>;
|
||||
})}
|
||||
{this.props.results.map((result) => (
|
||||
<li key={result.id}>{result.text}</li>
|
||||
))}
|
||||
</ol>
|
||||
);
|
||||
}
|
||||
@@ -128,41 +127,41 @@ The `key` should *always* be supplied directly to the components in the array, n
|
||||
|
||||
```javascript
|
||||
// WRONG!
|
||||
var ListItemWrapper = React.createClass({
|
||||
render: function() {
|
||||
class ListItemWrapper extends React.Component {
|
||||
render() {
|
||||
return <li key={this.props.data.id}>{this.props.data.text}</li>;
|
||||
}
|
||||
});
|
||||
var MyComponent = React.createClass({
|
||||
render: function() {
|
||||
}
|
||||
class MyComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<ul>
|
||||
{this.props.results.map(function(result) {
|
||||
return <ListItemWrapper data={result}/>;
|
||||
})}
|
||||
{this.props.results.map((result) => (
|
||||
<ListItemWrapper data={result} />
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
```javascript
|
||||
// Correct :)
|
||||
var ListItemWrapper = React.createClass({
|
||||
render: function() {
|
||||
class ListItemWrapper extends React.Component {
|
||||
render() {
|
||||
return <li>{this.props.data.text}</li>;
|
||||
}
|
||||
});
|
||||
var MyComponent = React.createClass({
|
||||
render: function() {
|
||||
}
|
||||
class MyComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<ul>
|
||||
{this.props.results.map(function(result) {
|
||||
return <ListItemWrapper key={result.id} data={result}/>;
|
||||
})}
|
||||
{this.props.results.map((result) => (
|
||||
<ListItemWrapper key={result.id} data={result} />
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
You can also key children by passing a ReactFragment object. See [Keyed Fragments](create-fragment.html) for more details.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: multiple-components-zh-CN
|
||||
title: 复合组件
|
||||
permalink: multiple-components-zh-CN.html
|
||||
permalink: docs/multiple-components-zh-CN.html
|
||||
prev: interactivity-and-dynamic-uis-zh-CN.html
|
||||
next: reusable-components-zh-CN.html
|
||||
---
|
||||
@@ -54,9 +54,9 @@ ReactDOM.render(
|
||||
|
||||
## 从属关系
|
||||
|
||||
上面例子中,`Avatar` 拥有 `PagePic` 和 `PageLink` 的实例。`拥有者` 就是给其它组件设置 `props` 的那个组件。更正式地说,如果组件 `Y` 在 `render()` 方法是创建了组件 `X`,那么 `Y` 就拥有 `X`。上面讲过,组件不能修改自身的 `props` - 它们总是与它们拥有者设置的保持一致。这是保持用户界面一致性的基本不变量。
|
||||
上面例子中,`Avatar` 拥有 `PagePic` 和 `PageLink` 的实例。`拥有者` 就是给其它组件设置 `props` 的那个组件。更正式地说,如果组件 `Y` 在 `render()` 方法是创建了组件 `X`,那么 `Y` 就拥有 `X`。上面讲过,组件不能修改自身的 `props` - 它们总是与它们的拥有者所设置的值保持一致。这是保持用户界面一致性的基本不变量。
|
||||
|
||||
把从属关系与父子关系加以区别至关重要。从属关系是 React 特有的,而父子关系简单来讲就是DOM 里的标签的关系。在上一个例子中,`Avatar` 拥有 `div`、`PagePic` 和 `PageLink` 实例,`div` 是 `PagePic` 和 `PageLink` 实例的**父级**(但不是拥有者)。
|
||||
把从属关系与父子关系加以区别至关重要。从属关系是 React 特有的,而父子关系简单来讲就是 DOM 里的标签的关系。在上一个例子中,`Avatar` 拥有 `div`、`PagePic` 和 `PageLink` 实例,`div` 是 `PagePic` 和 `PageLink` 实例的**父级**(但不是拥有者)。
|
||||
|
||||
## 子级
|
||||
|
||||
@@ -66,7 +66,7 @@ ReactDOM.render(
|
||||
<Parent><Child /></Parent>
|
||||
```
|
||||
|
||||
`Parent` 能通过专门的 `this.props.children` props 读取子级。**`this.props.children` 是一个不透明的数据结构:** 通过 [React.Children 工具类](/react/docs/top-level-api.html#react.children) 来操作。
|
||||
`Parent` 能通过专门的 `this.props.children` prop 读取子级。**`this.props.children` 是一个不透明的数据结构:** 通过 [React.Children 工具类](/react/docs/top-level-api.html#react.children) 来操作。
|
||||
|
||||
### 子级校正(Reconciliation)
|
||||
|
||||
@@ -123,7 +123,8 @@ ReactDOM.render(
|
||||
```
|
||||
|
||||
当 React 校正带有 key 的子级时,它会确保它们被重新排序(而不是破坏)或者删除(而不是重用)。
|
||||
`务必` 把 `key` 添加到子级数组里组件本身上,而不是每个子级内部最外层 HTML 上:
|
||||
|
||||
务必把 `key` 添加到子级数组中的组件本身上,而不是数组中每个子级组件内部的最外层 HTML 上:
|
||||
|
||||
```javascript
|
||||
// 错误!
|
||||
@@ -164,11 +165,11 @@ var MyComponent = React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
也可以传递ReactFragment 对象 来做有 key 的子级。详见[Keyed Fragments](create-fragment.html)
|
||||
也可以传递 ReactFragment 对象来做有 key 的子级。详见[Keyed Fragments](create-fragment.html)
|
||||
|
||||
## 数据流
|
||||
|
||||
React 里,数据通过上面介绍过的 `props` 从拥有者流向归属者。这就是高效的单向数据绑定(one-way data binding):拥有者通过它的 `props` 或 `state` 计算出一些值,并把这些值绑定到它们拥有的组件的 props 上。因为这个过程会递归地调用,所以数据变化会自动在所有被使用的地方自动反映出来。
|
||||
React 里,数据通过上面介绍过的 `props` 从拥有者流向归属者。这就是高效的单向数据绑定(one-way data binding):拥有者们通过它们的 `props` 或 `state` 计算出一些值,并把这些值绑定到它们拥有的组件的 props 上。因为这个过程会递归地调用,所以数据变化会自动在所有它们被使用的地方反映出来。
|
||||
|
||||
|
||||
## 性能提醒
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: reusable-components-it-IT
|
||||
title: Componenti Riutilizzabili
|
||||
permalink: reusable-components-it-IT.html
|
||||
permalink: docs/reusable-components-it-IT.html
|
||||
prev: multiple-components-it-IT.html
|
||||
next: transferring-props-it-IT.html
|
||||
---
|
||||
@@ -24,6 +24,7 @@ React.createClass({
|
||||
optionalNumber: React.PropTypes.number,
|
||||
optionalObject: React.PropTypes.object,
|
||||
optionalString: React.PropTypes.string,
|
||||
optionalSymbol: React.PropTypes.symbol,
|
||||
|
||||
// Tutto ciò che può essere mostrato: numeri, stringhe, elementi, o un array
|
||||
// (o frammento) contenente questi tipi.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: reusable-components
|
||||
title: 再利用可能なコンポーネント
|
||||
permalink: reusable-components-ja-JP.html
|
||||
permalink: docs/reusable-components-ja-JP.html
|
||||
prev: multiple-components-ja-JP.html
|
||||
next: transferring-props-ja-JP.html
|
||||
---
|
||||
@@ -23,6 +23,7 @@ React.createClass({
|
||||
optionalNumber: React.PropTypes.number,
|
||||
optionalObject: React.PropTypes.object,
|
||||
optionalString: React.PropTypes.string,
|
||||
optionalSymbol: React.PropTypes.symbol,
|
||||
|
||||
// 何でもレンダリングできます。number、string、要素やそれらを含む配列など。
|
||||
optionalNode: React.PropTypes.node,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: reusable-components-ko-KR
|
||||
title: 재사용가능한 컴포넌트
|
||||
permalink: reusable-components-ko-KR.html
|
||||
permalink: docs/reusable-components-ko-KR.html
|
||||
prev: multiple-components-ko-KR.html
|
||||
next: transferring-props-ko-KR.html
|
||||
---
|
||||
@@ -23,6 +23,7 @@ React.createClass({
|
||||
optionalNumber: React.PropTypes.number,
|
||||
optionalObject: React.PropTypes.object,
|
||||
optionalString: React.PropTypes.string,
|
||||
optionalSymbol: React.PropTypes.symbol,
|
||||
|
||||
// 렌더링될 수 있는 모든 것: 숫자, 문자열, 요소
|
||||
// 이것들을 포함하는 배열(이나 프래그먼트)
|
||||
@@ -139,7 +140,7 @@ var MyComponent = React.createClass({
|
||||
|
||||
컴포넌트는 React에서 코드를 재사용할 수 있는 최고의 방법이지만, 가끔 아주 다른 컴포넌트에서 공통 기능이 필요한 때도 있습니다. 이런 상황을 [공통된 관심사(cross-cutting concerns)](https://en.wikipedia.org/wiki/Cross-cutting_concern)라 부르며, React에서는 `mixins`으로 이 문제를 해결합니다.
|
||||
|
||||
예를 들어, 컴포넌트가 주기적으로 업데이트되길 원할 경우가 있습니다. `setInterval()`을 사용하면 쉽지만, 필요 없어지면 메모리를 아끼기 위해 주기를 꼭 취소해야 합니다. React는 컴포넌트가 막 생성거나 없어질 때를 [생명주기 메소드](/react/docs/working-with-the-browser-ko-KR.html#component-lifecycle)를 통해 알려줍니다. 이런 메소드들을 사용해서 컴포넌트가 사라질 때 자동으로 정리해주는 `setInterval()`를 제공해주는 간단한 믹스인을 만들어보겠습니다.
|
||||
예를 들어, 컴포넌트가 주기적으로 업데이트되길 원할 경우가 있습니다. `setInterval()`을 사용하면 쉽지만, 필요 없어지면 메모리를 아끼기 위해 주기를 꼭 취소해야 합니다. React는 컴포넌트가 막 생성거나 없어질 때를 [생명주기 메소드](/react/docs/working-with-the-browser-ko-KR.html#컴포넌트-생명주기)를 통해 알려줍니다. 이런 메소드들을 사용해서 컴포넌트가 사라질 때 자동으로 정리해주는 `setInterval()`를 제공해주는 간단한 믹스인을 만들어보겠습니다.
|
||||
|
||||
```javascript
|
||||
var SetIntervalMixin = {
|
||||
@@ -182,7 +183,6 @@ ReactDOM.render(
|
||||
|
||||
믹스인의 괜찮은 점은 컴포넌트가 여러 믹스인을 사용하고 여러 믹스인에서 같은 생명주기 메소드를 사용할 때(예를 들어, 여러 믹스인에서 컴포넌트가 사라질 때 뭔가 정리하려 한다면) 모든 생명주기 메소드들의 실행은 보장됩니다. 믹스인에 정의된 메소드은 컴포넌트의 메소드가 호출됨에 따라 믹스인이 나열된 순서대로 실행됩니다.
|
||||
|
||||
<a name="es6-classes"></a>
|
||||
## ES6 클래스
|
||||
|
||||
React 클래스를 일반적인 JavaScript 클래스로 선언할 수도 있습니다. 다음의 예제는 ES6 클래스 문법을 사용합니다:
|
||||
@@ -229,7 +229,6 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
|
||||
불행하게도 ES6는 믹스인에 대한 지원이 없이 출시되었기 때문에, React에서 ES6 클래스를 사용한다면 믹스인을 사용할 방법이 없습니다. 대신, 우리는 믹스인에 의존하지 않고도 동작하도록 만들기 위해 열심히 노력하고 있습니다.
|
||||
|
||||
<a name="stateless-functions"></a>
|
||||
## 상태를 가지지 않는 함수
|
||||
|
||||
React 클래스를 일반 JavaScript 함수로 작성할 수도 있습니다. 상태를 가지지 않는 함수 문법을 사용하는 예제입니다.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: reusable-components
|
||||
title: Reusable Components
|
||||
permalink: reusable-components.html
|
||||
permalink: docs/reusable-components.html
|
||||
prev: multiple-components.html
|
||||
next: transferring-props.html
|
||||
---
|
||||
@@ -10,89 +10,105 @@ When designing interfaces, break down the common design elements (buttons, form
|
||||
|
||||
## Prop Validation
|
||||
|
||||
As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify `propTypes`. `React.PropTypes` exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. Note that for performance reasons `propTypes` is only checked in development mode. Here is an example documenting the different validators provided:
|
||||
As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify `propTypes`. `React.PropTypes` exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. Note that for performance reasons `propTypes` is only checked in development mode.
|
||||
|
||||
You can assign a special property to a component to declare its `propTypes`:
|
||||
|
||||
```javascript
|
||||
React.createClass({
|
||||
propTypes: {
|
||||
// You can declare that a prop is a specific JS primitive. By default, these
|
||||
// are all optional.
|
||||
optionalArray: React.PropTypes.array,
|
||||
optionalBool: React.PropTypes.bool,
|
||||
optionalFunc: React.PropTypes.func,
|
||||
optionalNumber: React.PropTypes.number,
|
||||
optionalObject: React.PropTypes.object,
|
||||
optionalString: React.PropTypes.string,
|
||||
class Greeting extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<h1>Hello, {this.props.name}</h1>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Anything that can be rendered: numbers, strings, elements or an array
|
||||
// (or fragment) containing these types.
|
||||
optionalNode: React.PropTypes.node,
|
||||
Greeting.propTypes = {
|
||||
name: React.PropTypes.string
|
||||
};
|
||||
```
|
||||
|
||||
// A React element.
|
||||
optionalElement: React.PropTypes.element,
|
||||
Here is an example documenting the different validators provided:
|
||||
|
||||
// You can also declare that a prop is an instance of a class. This uses
|
||||
// JS's instanceof operator.
|
||||
optionalMessage: React.PropTypes.instanceOf(Message),
|
||||
```javascript
|
||||
MyComponent.propTypes = {
|
||||
// You can declare that a prop is a specific JS primitive. By default, these
|
||||
// are all optional.
|
||||
optionalArray: React.PropTypes.array,
|
||||
optionalBool: React.PropTypes.bool,
|
||||
optionalFunc: React.PropTypes.func,
|
||||
optionalNumber: React.PropTypes.number,
|
||||
optionalObject: React.PropTypes.object,
|
||||
optionalString: React.PropTypes.string,
|
||||
optionalSymbol: React.PropTypes.symbol,
|
||||
|
||||
// You can ensure that your prop is limited to specific values by treating
|
||||
// it as an enum.
|
||||
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
|
||||
// Anything that can be rendered: numbers, strings, elements or an array
|
||||
// (or fragment) containing these types.
|
||||
optionalNode: React.PropTypes.node,
|
||||
|
||||
// An object that could be one of many types
|
||||
optionalUnion: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.number,
|
||||
React.PropTypes.instanceOf(Message)
|
||||
]),
|
||||
// A React element.
|
||||
optionalElement: React.PropTypes.element,
|
||||
|
||||
// An array of a certain type
|
||||
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
|
||||
// You can also declare that a prop is an instance of a class. This uses
|
||||
// JS's instanceof operator.
|
||||
optionalMessage: React.PropTypes.instanceOf(Message),
|
||||
|
||||
// An object with property values of a certain type
|
||||
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
|
||||
// You can ensure that your prop is limited to specific values by treating
|
||||
// it as an enum.
|
||||
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
|
||||
|
||||
// An object taking on a particular shape
|
||||
optionalObjectWithShape: React.PropTypes.shape({
|
||||
color: React.PropTypes.string,
|
||||
fontSize: React.PropTypes.number
|
||||
}),
|
||||
// An object that could be one of many types
|
||||
optionalUnion: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.number,
|
||||
React.PropTypes.instanceOf(Message)
|
||||
]),
|
||||
|
||||
// You can chain any of the above with `isRequired` to make sure a warning
|
||||
// is shown if the prop isn't provided.
|
||||
requiredFunc: React.PropTypes.func.isRequired,
|
||||
// An array of a certain type
|
||||
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
|
||||
|
||||
// A value of any data type
|
||||
requiredAny: React.PropTypes.any.isRequired,
|
||||
// An object with property values of a certain type
|
||||
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
|
||||
|
||||
// You can also specify a custom validator. It should return an Error
|
||||
// object if the validation fails. Don't `console.warn` or throw, as this
|
||||
// won't work inside `oneOfType`.
|
||||
customProp: function(props, propName, componentName) {
|
||||
if (!/matchme/.test(props[propName])) {
|
||||
return new Error(
|
||||
'Invalid prop `' + propName + '` supplied to' +
|
||||
' `' + componentName + '`. Validation failed.'
|
||||
);
|
||||
}
|
||||
},
|
||||
// An object taking on a particular shape
|
||||
optionalObjectWithShape: React.PropTypes.shape({
|
||||
color: React.PropTypes.string,
|
||||
fontSize: React.PropTypes.number
|
||||
}),
|
||||
|
||||
// You can also supply a custom validator to `arrayOf` and `objectOf`.
|
||||
// It should return an Error object if the validation fails. The validator
|
||||
// will be called for each key in the array or object. The first two
|
||||
// arguments of the validator are the array or object itself, and the
|
||||
// current item's key.
|
||||
customArrayProp: React.PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
|
||||
if (!/matchme/.test(propValue[key])) {
|
||||
return new Error(
|
||||
'Invalid prop `' + propFullName + '` supplied to' +
|
||||
' `' + componentName + '`. Validation failed.'
|
||||
);
|
||||
}
|
||||
})
|
||||
// You can chain any of the above with `isRequired` to make sure a warning
|
||||
// is shown if the prop isn't provided.
|
||||
requiredFunc: React.PropTypes.func.isRequired,
|
||||
|
||||
// A value of any data type
|
||||
requiredAny: React.PropTypes.any.isRequired,
|
||||
|
||||
// You can also specify a custom validator. It should return an Error
|
||||
// object if the validation fails. Don't `console.warn` or throw, as this
|
||||
// won't work inside `oneOfType`.
|
||||
customProp: function(props, propName, componentName) {
|
||||
if (!/matchme/.test(props[propName])) {
|
||||
return new Error(
|
||||
'Invalid prop `' + propName + '` supplied to' +
|
||||
' `' + componentName + '`. Validation failed.'
|
||||
);
|
||||
}
|
||||
},
|
||||
/* ... */
|
||||
});
|
||||
|
||||
// You can also supply a custom validator to `arrayOf` and `objectOf`.
|
||||
// It should return an Error object if the validation fails. The validator
|
||||
// will be called for each key in the array or object. The first two
|
||||
// arguments of the validator are the array or object itself, and the
|
||||
// current item's key.
|
||||
customArrayProp: React.PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
|
||||
if (!/matchme/.test(propValue[key])) {
|
||||
return new Error(
|
||||
'Invalid prop `' + propFullName + '` supplied to' +
|
||||
' `' + componentName + '`. Validation failed.'
|
||||
);
|
||||
}
|
||||
})
|
||||
};
|
||||
```
|
||||
|
||||
### Single Child
|
||||
@@ -100,20 +116,21 @@ React.createClass({
|
||||
With `React.PropTypes.element` you can specify that only a single child can be passed to a component as children.
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
class MyComponent extends React.Component {
|
||||
render() {
|
||||
// This must be exactly one element or it will warn.
|
||||
var children = this.props.children;
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // This must be exactly one element or it will warn.
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
MyComponent.propTypes = {
|
||||
children: React.PropTypes.element.isRequired
|
||||
};
|
||||
```
|
||||
|
||||
## Default Prop Values
|
||||
@@ -121,29 +138,41 @@ var MyComponent = React.createClass({
|
||||
React lets you define default values for your `props` in a very declarative way:
|
||||
|
||||
```javascript
|
||||
var ComponentWithDefaultProps = React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
value: 'default value'
|
||||
};
|
||||
class Greeting extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<h1>Hello, {this.props.name}</h1>
|
||||
);
|
||||
}
|
||||
/* ... */
|
||||
});
|
||||
}
|
||||
|
||||
// Specifies the default values for props:
|
||||
Greeting.defaultProps = {
|
||||
name: 'Stranger'
|
||||
};
|
||||
|
||||
// Renders "Hello, Stranger":
|
||||
ReactDOM.render(
|
||||
<Greeting />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
The result of `getDefaultProps()` will be cached and used to ensure that `this.props.value` will have a value if it was not specified by the parent component. This allows you to safely just use your props without having to write repetitive and fragile code to handle that yourself.
|
||||
The `defaultProps` will be used to ensure that `this.props.name` will have a value if it was not specified by the parent component. This allows you to safely just use your props without having to write repetitive and fragile code to handle that yourself.
|
||||
|
||||
## Transferring Props: A Shortcut
|
||||
|
||||
A common type of React component is one that extends a basic HTML element in a simple way. Often you'll want to copy any HTML attributes passed to your component to the underlying HTML element. To save typing, you can use the JSX _spread_ syntax to achieve this:
|
||||
|
||||
```javascript
|
||||
var CheckLink = React.createClass({
|
||||
render: function() {
|
||||
class CheckLink extends React.Component {
|
||||
render() {
|
||||
// This takes any props passed to CheckLink and copies them to <a>
|
||||
return <a {...this.props}>{'√ '}{this.props.children}</a>;
|
||||
return (
|
||||
<a {...this.props}>{'√ '}{this.props.children}</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<CheckLink href="/checked.html">
|
||||
@@ -153,9 +182,241 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
## Mixins
|
||||
## Stateless Functions
|
||||
|
||||
Components are the best way to reuse code in React, but sometimes very different components may share some common functionality. These are sometimes called [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). React provides `mixins` to solve this problem.
|
||||
If a component doesn't use local state or lifecycle hooks, you can define it as a function instead of a class:
|
||||
|
||||
```javascript
|
||||
function Greeting(props) {
|
||||
return <h1>Hello, {props.name}</h1>;
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<Greeting name="Sebastian" />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
Or using the new ES6 arrow syntax:
|
||||
|
||||
```javascript
|
||||
const Greeting = (props) => (
|
||||
<h1>Hello, {props.name}</h1v>
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<Greeting name="Sebastian" />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
This simplified component API is intended for components that are pure functions of their props. These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate.
|
||||
|
||||
However, you may still specify `.propTypes` and `.defaultProps` by setting them as properties on the function, just as you would set them on an ES6 class:
|
||||
|
||||
```javascript
|
||||
function Greeting(props) {
|
||||
return (
|
||||
<h1>Hello, {props.name}</h1v>
|
||||
);
|
||||
}
|
||||
|
||||
Greeting.propTypes = {
|
||||
name: React.PropTypes.string
|
||||
};
|
||||
|
||||
Greeting.defaultProps = {
|
||||
name: 'John Doe'
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<Greeting name="Mădălina"/>,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
>**Note:**
|
||||
>
|
||||
> Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component. Normally this isn't an issue, since stateless functions do not provide an imperative API. Without an imperative API, there isn't much you could do with an instance anyway. However, if a user wants to find the DOM node of a stateless function component, they must wrap the component in a stateful component (eg. ES6 class component) and attach the ref to the stateful wrapper component.
|
||||
|
||||
In an ideal world, many of your components would be stateless functions. In the future we plan to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations.
|
||||
|
||||
When you don't need local state or lifecycle hooks in a component, we recommend declaring it with a function. Otherwise, we recommend to use the ES6 class syntax.
|
||||
|
||||
## ES6 Classes and React.createClass()
|
||||
|
||||
Normally you would define a React component as a plain JavaScript class:
|
||||
|
||||
```javascript
|
||||
class Greeting extends React.Component {
|
||||
render() {
|
||||
return <h1>Hello, {this.props.name}</h1>;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you don't use ES6 yet, you may use [`React.createClass`](/react/docs/top-level-api.html#react.createclass) helper instead:
|
||||
|
||||
|
||||
```javascript
|
||||
var Greeting = React.createClass({
|
||||
render: function() {
|
||||
return <h1>Hello, {this.props.name}</h1>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
The API of ES6 classes is similar to [`React.createClass`](/react/docs/top-level-api.html#react.createclass) with a few exceptions.
|
||||
|
||||
### Declaring Prop Types and Default Props
|
||||
|
||||
With functions and ES6 classes, `propTypes` and `defaultProps` are defined as properties on the components themselves:
|
||||
|
||||
```javascript
|
||||
class Greeting extends React.Component {
|
||||
// ...
|
||||
}
|
||||
|
||||
Greeting.propTypes = {
|
||||
name: React.PropTypes.string
|
||||
};
|
||||
|
||||
Greeting.defaultProps = {
|
||||
name: 'Mary'
|
||||
};
|
||||
```
|
||||
|
||||
With `React.createClass()`, you need to define `propTypes` as a property on the passed object, and `getDefaultProps()` as a function on it:
|
||||
|
||||
```javascript
|
||||
var Greeting = React.createClass({
|
||||
propTypes: {
|
||||
name: React.PropTypes.string
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
name: 'Mary'
|
||||
};
|
||||
},
|
||||
|
||||
// ...
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
### Setting the Initial State
|
||||
|
||||
In ES6 classes, you can define the initial state by assigning `this.state` in the constructor:
|
||||
|
||||
```javascript
|
||||
class Counter extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {count: props.initialCount};
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
With `React.createClass()`, you have to provide a separate `getInitialState` method that returns the initial state:
|
||||
|
||||
```javascript
|
||||
var Counter = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {count: props.initialCount};
|
||||
},
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### Autobinding
|
||||
|
||||
In React components declared as ES6 classes, methods follow the same semantics as regular ES6 classes. This means that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` in the constructor:
|
||||
|
||||
```javascript
|
||||
class SayHello extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
// This line is important!
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
alert('Hello!');
|
||||
}
|
||||
|
||||
render() {
|
||||
// Because we `this.tick` is bound, we can use it as an event handler.
|
||||
return (
|
||||
<button onClick={this.handleClick}>
|
||||
Say hello
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With `React.createClass()`, this is not necessary because it binds all methods:
|
||||
|
||||
```javascript
|
||||
var SayHello = React.createClass({
|
||||
handleClick: function() {
|
||||
alert('Hello!');
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<button onClick={this.handleClick}>
|
||||
Say hello
|
||||
</button>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
This means writing ES6 classes comes with a little more boilerplate code for event handlers, but the upside is slightly better performance in large applications.
|
||||
|
||||
If the boilerplate code is too unattractive to you, you may enable the **experimental** [Class Properties](https://babeljs.io/docs/plugins/transform-class-properties/) syntax proposal with Babel:
|
||||
|
||||
|
||||
```javascript
|
||||
class SayHello extends React.Component {
|
||||
// WARNING: this syntax is experimental!
|
||||
// Using an arrow here binds the method:
|
||||
handleClick = () => {
|
||||
alert('Hello!');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<button onClick={this.handleClick}>
|
||||
Say hello
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Please note that the syntax above is **experimental** and the syntax may change, or the proposal might not make it into the language.
|
||||
|
||||
If you'd rather play it safe, you have a few options:
|
||||
|
||||
* Bind methods in the constructor.
|
||||
* Use arrow functions, e.g. `onClick={(e) => this.handleClick(e)})`.
|
||||
* Keep using `React.createClass()`.
|
||||
|
||||
### Mixins
|
||||
|
||||
>**Note:**
|
||||
>
|
||||
>ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes.
|
||||
>
|
||||
>**We also found numerous issues in codebases using mixins, [and don't recommend using them in the new code](/react/blog/2016/07/13/mixins-considered-harmful.html).**
|
||||
>
|
||||
>This section exists only for the reference.
|
||||
|
||||
Sometimes very different components may share some common functionality. These are sometimes called [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). [`React.createClass`](/react/docs/top-level-api.html#react.createclass) lets you use a legacy `mixins` system for that.
|
||||
|
||||
One common use case is a component wanting to update itself on a time interval. It's easy to use `setInterval()`, but it's important to cancel your interval when you don't need it anymore to save memory. React provides [lifecycle methods](/react/docs/working-with-the-browser.html#component-lifecycle) that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy `setInterval()` function that will automatically get cleaned up when your component is destroyed.
|
||||
|
||||
@@ -198,105 +459,4 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
A nice feature of mixins is that if a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.
|
||||
|
||||
## ES6 Classes
|
||||
|
||||
You may also define your React classes as a plain JavaScript class. For example using ES6 class syntax:
|
||||
|
||||
```javascript
|
||||
class HelloMessage extends React.Component {
|
||||
render() {
|
||||
return <div>Hello {this.props.name}</div>;
|
||||
}
|
||||
}
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
The API is similar to `React.createClass` with the exception of `getInitialState`. Instead of providing a separate `getInitialState` method, you set up your own `state` property in the constructor.
|
||||
|
||||
Another difference is that `propTypes` and `defaultProps` are defined as properties on the constructor instead of in the class body.
|
||||
|
||||
```javascript
|
||||
export class Counter extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {count: props.initialCount};
|
||||
this.tick = this.tick.bind(this);
|
||||
}
|
||||
tick() {
|
||||
this.setState({count: this.state.count + 1});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div onClick={this.tick}>
|
||||
Clicks: {this.state.count}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Counter.propTypes = { initialCount: React.PropTypes.number };
|
||||
Counter.defaultProps = { initialCount: 0 };
|
||||
```
|
||||
|
||||
### No Autobinding
|
||||
|
||||
Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` or [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `=>`:
|
||||
|
||||
```javascript
|
||||
// You can use bind() to preserve `this`
|
||||
<div onClick={this.tick.bind(this)}>
|
||||
|
||||
// Or you can use arrow functions
|
||||
<div onClick={() => this.tick()}>
|
||||
```
|
||||
|
||||
We recommend that you bind your event handlers in the constructor so they are only bound once for every instance:
|
||||
|
||||
```javascript
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {count: props.initialCount};
|
||||
this.tick = this.tick.bind(this);
|
||||
}
|
||||
```
|
||||
|
||||
Now you can use `this.tick` directly as it was bound once in the constructor:
|
||||
|
||||
```javascript
|
||||
// It is already bound in the constructor
|
||||
<div onClick={this.tick}>
|
||||
```
|
||||
|
||||
This is better for performance of your application, especially if you implement [shouldComponentUpdate()](/react/docs/component-specs.html#updating-shouldcomponentupdate) with a [shallow comparison](/react/docs/shallow-compare.html) in the child components.
|
||||
|
||||
### No Mixins
|
||||
|
||||
Unfortunately ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes. Instead, we're working on making it easier to support such use cases without resorting to mixins.
|
||||
|
||||
## Stateless Functions
|
||||
|
||||
You may also define your React classes as a plain JavaScript function. For example using the stateless function syntax:
|
||||
|
||||
```javascript
|
||||
function HelloMessage(props) {
|
||||
return <div>Hello {props.name}</div>;
|
||||
}
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
Or using the new ES6 arrow syntax:
|
||||
|
||||
```javascript
|
||||
const HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
This simplified component API is intended for components that are pure functions of their props. These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate.
|
||||
However, you may still specify `.propTypes` and `.defaultProps` by setting them as properties on the function, just as you would set them on an ES6 class.
|
||||
|
||||
> NOTE:
|
||||
>
|
||||
> Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component. Normally this isn't an issue, since stateless functions do not provide an imperative API. Without an imperative API, there isn't much you could do with an instance anyway. However, if a user wants to find the DOM node of a stateless function component, they must wrap the component in a stateful component (eg. ES6 class component) and attach the ref to the stateful wrapper component.
|
||||
|
||||
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.
|
||||
If a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: reusable-components-zh-CN
|
||||
title: 可复用组件
|
||||
permalink: reusable-components-zh-CN.html
|
||||
permalink: docs/reusable-components-zh-CN.html
|
||||
prev: multiple-components-zh-CN.html
|
||||
next: transferring-props-zh-CN.html
|
||||
---
|
||||
@@ -23,6 +23,7 @@ React.createClass({
|
||||
optionalNumber: React.PropTypes.number,
|
||||
optionalObject: React.PropTypes.object,
|
||||
optionalString: React.PropTypes.string,
|
||||
optionalSymbol: React.PropTypes.symbol,
|
||||
|
||||
// 所有可以被渲染的对象:数字,
|
||||
// 字符串,DOM 元素或包含这些类型的数组(or fragment) 。
|
||||
@@ -118,7 +119,7 @@ var ComponentWithDefaultProps = React.createClass({
|
||||
|
||||
## 传递 Props:捷径
|
||||
|
||||
有一些常用的 React 组件只是对 HTML 做简单扩展。通常,你想 复制任何传进你的组件的HTML属性 到底层的HTML元素上。为了减少输入,你可以用 JSX _spread_ 语法来完成:
|
||||
有一些常用的 React 组件只是对 HTML 做简单扩展。通常,你想复制任何传进你的组件的HTML属性到底层的HTML元素上。为了减少输入,你可以用 JSX _spread_ 语法来完成:
|
||||
|
||||
```javascript
|
||||
var CheckLink = React.createClass({
|
||||
@@ -138,9 +139,9 @@ ReactDOM.render(
|
||||
|
||||
## Mixins
|
||||
|
||||
组件是 React 里复用代码最佳方式,但是有时一些复杂的组件间也需要共用一些功能。有时会被称为 [跨切面关注点](https://en.wikipedia.org/wiki/Cross-cutting_concern)。React 使用 `mixins` 来解决这类问题。
|
||||
组件是 React 里复用代码的最佳方式,但是有时一些不同的组件间也需要共用一些功能。有时会被称为 [跨切面关注点](https://en.wikipedia.org/wiki/Cross-cutting_concern)。React 使用 `mixins` 来解决这类问题。
|
||||
|
||||
一个通用的场景是:一个组件需要定期更新。用 `setInterval()` 做很容易,但当不需要它的时候取消定时器来节省内存是非常重要的。React 提供 [生命周期方法](/react/docs/working-with-the-browser.html#component-lifecycle) 来告知组件创建或销毁的时间。下面来做一个简单的 mixin,使用 `setInterval()` 并保证在组件销毁时清理定时器。
|
||||
一个通用的场景是:一个组件需要定期更新。用 `setInterval()` 做很容易,但当不需要它的时候取消定时器来节省内存是非常重要的。React 提供 [生命周期方法](/react/docs/working-with-the-browser.html#component-lifecycle) 来告知你组件创建或销毁的时间。下面来做一个简单的 mixin,使用 `setInterval()` 并保证在组件销毁时清理定时器。
|
||||
|
||||
```javascript
|
||||
var SetIntervalMixin = {
|
||||
@@ -185,7 +186,7 @@ ReactDOM.render(
|
||||
|
||||
## ES6 Classes
|
||||
|
||||
你也可以以一个简单的JavaScript 类来定义你的React classes。使用ES6 class的例子:
|
||||
你也可以以一个简单的 JavaScript 类来定义你的React classes。使用ES6 class的例子:
|
||||
|
||||
```javascript
|
||||
class HelloMessage extends React.Component {
|
||||
@@ -196,9 +197,9 @@ class HelloMessage extends React.Component {
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
API近似于 `React.createClass` 除了 `getInitialState`。 你应该在构造函数里设置你的`state`,而不是提供一个单独的 `getInitialState` 方法。
|
||||
API近似于 `React.createClass` 除了 `getInitialState`。 你应该在构造函数里设置你的`state`,而不是提供一个单独的 `getInitialState` 方法。就像 `getInitialState` 的返回值,你赋给 `this.state` 的值会被作为组件的初始 state。
|
||||
|
||||
另一个不同是 `propTypes` 和 `defaultProps` 在构造函数而不是class body里被定义为属性。
|
||||
另一个不同是 `propTypes` 和 `defaultProps` 是在构造函数里被定义为属性,而不是在 class body 里。
|
||||
|
||||
```javascript
|
||||
export class Counter extends React.Component {
|
||||
@@ -223,11 +224,38 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
|
||||
### 无自动绑定
|
||||
|
||||
方法遵循正式的ES6 class的语义,意味着它们不会自动绑定`this`到实例上。你必须显示的使用`.bind(this)` or [箭头函数](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `=>`.
|
||||
方法遵循正式的ES6 class的语义,意味着它们不会自动绑定`this`到实例上。你必须显示的使用`.bind(this)` or [箭头函数](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `=>`:
|
||||
|
||||
```javascript
|
||||
// 你可以使用 bind() 来绑定 `this`
|
||||
<div onClick={this.tick.bind(this)}>
|
||||
|
||||
// 或者你可以使用箭头函数
|
||||
<div onClick={() => this.tick()}>
|
||||
```
|
||||
|
||||
我们建议你在构造函数中绑定事件处理器,这样对于所有实例它们只需绑定一次:
|
||||
|
||||
```javascript
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {count: props.initialCount};
|
||||
this.tick = this.tick.bind(this);
|
||||
}
|
||||
```
|
||||
|
||||
现在你可以直接使用 `this.tick` 因为它已经在构造函数里绑定过一次了。
|
||||
|
||||
```javascript
|
||||
// 它已经在构造函数里绑定过了
|
||||
<div onClick={this.tick}>
|
||||
```
|
||||
|
||||
这对应用的性能有帮助,特别是当你用 [浅层比较](/react/docs/shallow-compare.html) 实现 [shouldComponentUpdate()](/react/docs/component-specs.html#updating-shouldcomponentupdate) 时。
|
||||
|
||||
### 没有 Mixins
|
||||
|
||||
不幸的是ES6的发布没有任何mixin的支持。因此,当你在ES6 classes下使用React时不支持mixins。作为替代,我们正在努力使它更容易支持这些用例不依靠mixins。
|
||||
不幸的是ES6的发布没有任何mixin的支持。因此,当你在ES6 classes下使用React时不支持mixins。作为替代,我们正在努力使它更容易不依靠mixins支持这些用例。
|
||||
|
||||
## 无状态函数
|
||||
|
||||
@@ -248,7 +276,7 @@ ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
这个简化的组件API旨在用于那些纯函数态的组件 。这些组件必须没有保持任何内部状态,没有备份实例,也没有组件生命周期方法。他们纯粹的函数式的转化他们的输入,没有引用。
|
||||
然而,你仍然可以以设置为函数的properties的方式来指定 `.propTypes` 和 `.defaultProps`,就像你在ES6类里设置他们那样。
|
||||
然而,你仍然可以以设置函数 properties 的方式来指定 `.propTypes` 和 `.defaultProps`,就像你在ES6类里设置他们那样。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: transferring-props-it-IT
|
||||
title: Trasferimento delle Proprietà
|
||||
permalink: transferring-props-it-IT.html
|
||||
permalink: docs/transferring-props-it-IT.html
|
||||
prev: reusable-components-it-IT.html
|
||||
next: forms-it-IT.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: transferring-props
|
||||
title: propsの移譲
|
||||
permalink: transferring-props-ja-JP.html
|
||||
permalink: docs/transferring-props-ja-JP.html
|
||||
prev: reusable-components-ja-JP.html
|
||||
next: forms-ja-JP.html
|
||||
|
||||
@@ -50,7 +50,7 @@ ReactDOM.render(
|
||||
## JSXにおける `...` を使った移譲
|
||||
|
||||
> 注意:
|
||||
> 以下の例では、実験的なES7のシンタックスであることを示すために `--harmony ` フラグが必要になります。ブラウザ上でJSXトランスフォーマーを使う際には、単純に `<script type="text/jsx;harmony=true">` を使ってスクリプトを読み込んでください。詳細については、 [レストとスプレッドのプロパティ ...](/react/docs/transferring-props.html#rest-and-spread-properties-...)をご覧ください。
|
||||
> 以下の例では、実験的なES7のシンタックスであることを示すために `--harmony ` フラグが必要になります。ブラウザ上でJSXトランスフォーマーを使う際には、単純に `<script type="text/jsx;harmony=true">` を使ってスクリプトを読み込んでください。詳細については、 [レストとスプレッドのプロパティ ...](/react/docs/transferring-props-ja-JP.html#レストとスプレッドのプロパティ-...)をご覧ください。
|
||||
|
||||
全てのプロパティを渡すのはバグを生みやすく、面倒くさいときがあります。そのようなケースでは、未知のプロパティのセットを使うためにレストプロパティと共に[分割代入引数](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)を使うことができます。
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: transferring-props-ko-KR
|
||||
title: Props 전달
|
||||
permalink: transferring-props-ko-KR.html
|
||||
permalink: docs/transferring-props-ko-KR.html
|
||||
prev: reusable-components-ko-KR.html
|
||||
next: forms-ko-KR.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: transferring-props
|
||||
title: Transferring Props
|
||||
permalink: transferring-props.html
|
||||
permalink: docs/transferring-props.html
|
||||
prev: reusable-components.html
|
||||
next: forms.html
|
||||
---
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
id: transferring-props-zh-CN
|
||||
title: 传递 Props
|
||||
permalink: transferring-props-zh-CN.html
|
||||
permalink: docs/transferring-props-zh-CN.html
|
||||
prev: reusable-components-zh-CN.html
|
||||
next: forms-zh-CN.html
|
||||
---
|
||||
|
||||
React 里有一个非常常用的模式就是对组件做一层抽象。组件对外公开一个简单的属性(Props)来实现功能,但内部细节可能有非常复杂的实现。
|
||||
React 里有一个非常常用的模式就是对组件做一层抽象。组件对外公开一个简单的属性(Props)来实现功能,但内部的实现可能非常复杂。
|
||||
|
||||
可以使用 [JSX 展开属性](/react/docs/jsx-spread-zh-CN.html) 来合并现有的 props 和其它值:
|
||||
|
||||
@@ -49,11 +49,11 @@ ReactDOM.render(
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 在下面的例子中,`--harmony ` 标志是必须的因为这个语法是ES7的实验性语法。如果用浏览器中的JSX转换器,以 `<script type="text/jsx;harmony=true">`简单的打开你脚本就行了。详见[Rest and Spread Properties ...](/react/docs/transferring-props.html#rest-and-spread-properties-...)
|
||||
> 在下面的例子中,`--harmony ` 标志是必须的因为这个语法是ES7的实验性语法。如果用浏览器中的JSX转换器,以 `<script type="text/jsx;harmony=true">`简单的打开你脚本就行了。详见[Rest and Spread Properties ...](/react/docs/transferring-props-zh-CN.html#剩余属性和展开属性-...)
|
||||
|
||||
有时把所有属性都传下去是不安全或啰嗦的。这时可以使用 [解构赋值](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) 中的剩余属性特性来把未知属性批量提取出来。
|
||||
|
||||
列出所有要当前使用的属性,后面跟着 `...other`。
|
||||
列出所有当前要使用的属性,后面跟着 `...other`。
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = props;
|
||||
@@ -118,11 +118,11 @@ function FancyCheckbox(props) {
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 顺序很重要,把 `{...other}` 放到 JSX props 前面会使它不被覆盖。上面例子中我们可以保证 input 的 type 是 `"checkbox"`。
|
||||
> 顺序很重要,把 `{...other}` 放到 JSX props 前面会使 props 不会被覆盖。上面例子中我们可以保证 input 的 type 是 `"checkbox"`。
|
||||
|
||||
## 剩余属性和展开属性 `...`
|
||||
|
||||
剩余属性可以把对象剩下的属性提取到一个新的对象。会把所有在解构赋值中列出的属性剔除。
|
||||
剩余属性可以把对象剩下的属性提取到一个新的对象。这会把所有在解构赋值中列出的属性剔除。
|
||||
|
||||
这是 [ECMAScript 草案](https://github.com/sebmarkbage/ecmascript-rest-spread) 中的试验特性。
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: forms-it-IT
|
||||
title: Moduli
|
||||
permalink: forms-it-IT.html
|
||||
permalink: docs/forms-it-IT.html
|
||||
prev: transferring-props-it-IT.html
|
||||
next: working-with-the-browser-it-IT.html
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: forms
|
||||
title: フォーム
|
||||
permalink: forms-ja-JP.html
|
||||
permalink: docs/forms-ja-JP.html
|
||||
prev: transferring-props-ja-JP.html
|
||||
next: working-with-the-browser-ja-JP.html
|
||||
---
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
id: forms-ko-KR
|
||||
title: 폼
|
||||
permalink: forms-ko-KR.html
|
||||
permalink: docs/forms-ko-KR.html
|
||||
prev: transferring-props-ko-KR.html
|
||||
next: working-with-the-browser-ko-KR.html
|
||||
---
|
||||
|
||||
`<input>`, `<textarea>`, `<option>` 같은 폼 컴포넌트는 다른 네이티브 컴포넌트와 다릅니다. 왜냐하면, 사용자의 상호작용에 의해 변경될 수 있기 때문이죠. 이런 컴포넌트들은 사용자의 상호작용에 반응하여 폼을 더 쉽게 관리할 수 있도록 인터페이스를 제공합니다.
|
||||
|
||||
`<form>` 이벤트에 관한 정보는 [폼 이벤트](/react/docs/events-ko-KR.html#form-events)를 보세요.
|
||||
`<form>` 이벤트에 관한 정보는 [폼 이벤트](/react/docs/events-ko-KR.html#폼-이벤트)를 보세요.
|
||||
|
||||
## Props의 상호작용
|
||||
|
||||
@@ -32,7 +32,6 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
>
|
||||
> `<input>`, `<textarea>`에서는 `onChange`가 DOM의 [`oninput`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput) 이벤트 핸들러와 같은 기능을 제공하므로 일반적인 경우에는 `onChange`를 사용하세요.
|
||||
|
||||
<a name="controlled-components"></a>
|
||||
## 제어되는(controlled) 컴포넌트
|
||||
|
||||
`value`가 설정된 `<input>`은 *제어되는* 컴포넌트입니다. 제어되는 `<input>`에서, 렌더 엘리먼트의 값은 항상 `value` prop을 반영합니다. 예를 들어,
|
||||
@@ -68,9 +67,9 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
|
||||
이것은 사용자 입력을 받아들이지만, 시작에서부터 140자로 값을 자릅니다.
|
||||
|
||||
### 체크박스와 라디오 버튼의 잠제적인 문제
|
||||
### 체크박스와 라디오 버튼의 잠재적인 문제
|
||||
|
||||
변경 핸들링을 일반화하기 위해 React는 `change` 이벤트 대신에 `click` 이벤트를 사용하는 것에 주의하세요. `change` 핸들러 안에서 `preventDefault`를 호출하는 경우를 재외하고 이 동작은 예상대로 동작합니다. 이런 경우 `preventDefault`를 제거하거나, `setTimeout`에 `checked`의 전환을 넣어서 해결 가능합니다.
|
||||
변경 핸들링을 일반화하기 위해 React는 `change` 이벤트 대신에 `click` 이벤트를 사용하는 것에 주의하세요. `change` 핸들러 안에서 `preventDefault`를 호출하는 경우를 제외하고 이 동작은 예상대로 동작합니다. 이런 경우 `preventDefault`를 제거하거나, `setTimeout`에 `checked`의 전환을 넣어서 해결 가능합니다.
|
||||
|
||||
## 제어되지 않는(Uncontrolled) 컴포넌트
|
||||
|
||||
@@ -100,7 +99,7 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> `defaultValue`, `defaultChecked` prop은 최초 렌더에서만 사용됩니다. 뒤에 일어나는 렌더에서 값을 업데이트할 필요가 있다면, [제어되는(controlled) 컴포넌트](#controlled-components)를 사용하셔야 합니다.
|
||||
> `defaultValue`, `defaultChecked` prop은 최초 렌더에서만 사용됩니다. 뒤에 일어나는 렌더에서 값을 업데이트할 필요가 있다면, [제어되는(controlled) 컴포넌트](#제어되는controlled-컴포넌트)를 사용하셔야 합니다.
|
||||
|
||||
## 심화 주제
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: forms
|
||||
title: Forms
|
||||
permalink: forms.html
|
||||
permalink: docs/forms.html
|
||||
prev: transferring-props.html
|
||||
next: working-with-the-browser.html
|
||||
---
|
||||
@@ -37,7 +37,7 @@ Like all DOM events, the `onChange` prop is supported on all native components a
|
||||
A **controlled** `<input>` has a `value` prop. Rendering a controlled `<input>` will reflect the value of the `value` prop.
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
render() {
|
||||
return <input type="text" value="Hello!" />;
|
||||
}
|
||||
```
|
||||
@@ -45,13 +45,18 @@ A **controlled** `<input>` has a `value` prop. Rendering a controlled `<input>`
|
||||
User input will have no effect on the rendered element because React has declared the value to be `Hello!`. To update the value in response to user input, you could use the `onChange` event:
|
||||
|
||||
```javascript
|
||||
getInitialState: function() {
|
||||
return {value: 'Hello!'};
|
||||
},
|
||||
handleChange: function(event) {
|
||||
class MyForm extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {value: 'Hello!'};
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
|
||||
handleChange(event) {
|
||||
this.setState({value: event.target.value});
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
@@ -60,12 +65,13 @@ User input will have no effect on the rendered element because React has declare
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this example, we are accepting the value provided by the user and updating the `value` prop of the `<input>` component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. For example:
|
||||
|
||||
```javascript
|
||||
handleChange: function(event) {
|
||||
handleChange(event) {
|
||||
this.setState({value: event.target.value.substr(0, 140)});
|
||||
}
|
||||
```
|
||||
@@ -83,7 +89,7 @@ Be aware that, in an attempt to normalize change handling for checkbox and radio
|
||||
An `<input>` without a `value` property is an *uncontrolled* component:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
render() {
|
||||
return <input type="text" />;
|
||||
}
|
||||
```
|
||||
@@ -97,7 +103,7 @@ An **uncontrolled** component maintains its own internal state.
|
||||
If you want to initialize the component with a non-empty value, you can supply a `defaultValue` prop. For example:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
render() {
|
||||
return <input type="text" defaultValue="Hello!" />;
|
||||
}
|
||||
```
|
||||
@@ -125,7 +131,7 @@ This renders an input *initialized* with the value, `Untitled`. When the user up
|
||||
Unlike HTML, React components must represent the state of the view at any point in time and not only at initialization time. For example, in React:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
render() {
|
||||
return <input type="text" name="title" value="Untitled" />;
|
||||
}
|
||||
```
|
||||
@@ -166,3 +172,8 @@ To make an uncontrolled component, `defaultValue` is used instead.
|
||||
> Note:
|
||||
>
|
||||
> You can pass an array into the `value` attribute, allowing you to select multiple options in a `select` tag: `<select multiple={true} value={['B', 'C']}>`.
|
||||
|
||||
### Imperative operations
|
||||
|
||||
If you need to imperatively perform an operation, you have to obtain a [reference to the DOM node](/react/docs/more-about-refs.html#the-ref-callback-attribute).
|
||||
For instance, if you want to imperatively submit a form, one approach would be to attach a `ref` to the `form` element and manually call `form.submit()`.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user