Compare commits
607 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
283f4a8b04 | ||
|
|
393a889aac | ||
|
|
3e455a4397 | ||
|
|
91b2ac57d4 | ||
|
|
c8996773ae | ||
|
|
a2a7536f38 | ||
|
|
ce478822e8 | ||
|
|
b88f97f9be | ||
|
|
ddbf91afd1 | ||
|
|
ae95674173 | ||
|
|
9e11fb626e | ||
|
|
ec746d3a1b | ||
|
|
91976ea8b4 | ||
|
|
9040c5f3a8 | ||
|
|
08d72df56b | ||
|
|
d6edc1189a | ||
|
|
6f532a839f | ||
|
|
34589c0e0d | ||
|
|
d91b238015 | ||
|
|
db904c2597 | ||
|
|
c12929700a | ||
|
|
30a11d2d7e | ||
|
|
a5115a2489 | ||
|
|
8b1990caa7 | ||
|
|
007d8b4f79 | ||
|
|
e6b5013a8b | ||
|
|
e4fa9ca9ee | ||
|
|
176ef3521c | ||
|
|
58635eea36 | ||
|
|
f8737dc8fe | ||
|
|
01297cf212 | ||
|
|
89437e6a97 | ||
|
|
ed755945a3 | ||
|
|
018e08cdd8 | ||
|
|
949c69fd56 | ||
|
|
a244928353 | ||
|
|
c034435052 | ||
|
|
8795a78ca0 | ||
|
|
123d091cc0 | ||
|
|
764ca84e02 | ||
|
|
3d78d30f49 | ||
|
|
fae1c48470 | ||
|
|
9801937715 | ||
|
|
0cac12d375 | ||
|
|
1e2d37f7e8 | ||
|
|
38bce710ac | ||
|
|
2e43de20cc | ||
|
|
a41aa76ef3 | ||
|
|
bdf2a9bb12 | ||
|
|
8d48610b7e | ||
|
|
759425fc90 | ||
|
|
2ee66262db | ||
|
|
260d90ba02 | ||
|
|
492407bcc9 | ||
|
|
374c3b8a29 | ||
|
|
c362c16e1e | ||
|
|
ddb0ef98f7 | ||
|
|
8dd4428c55 | ||
|
|
795a84d60f | ||
|
|
947e17154a | ||
|
|
7f8b2885d9 | ||
|
|
d1c5cda93f | ||
|
|
fa5da5c848 | ||
|
|
734ee22a0c | ||
|
|
84dbb9bcd1 | ||
|
|
8ed80cae94 | ||
|
|
8b995ceb6a | ||
|
|
975b5d978f | ||
|
|
f1231e60b0 | ||
|
|
4deb0d619c | ||
|
|
cf3ff07f92 | ||
|
|
bbb4a367be | ||
|
|
63d6cc013e | ||
|
|
d1d2d8d463 | ||
|
|
74cfc9c274 | ||
|
|
add809be21 | ||
|
|
579d86f024 | ||
|
|
73ceb5a401 | ||
|
|
2b9dd04f4d | ||
|
|
4f53fbf1a2 | ||
|
|
64d72f8c4b | ||
|
|
50a00662cf | ||
|
|
d7fcbe0f96 | ||
|
|
0441d4c7f5 | ||
|
|
d9aa2bd12c | ||
|
|
222faf4544 | ||
|
|
36fbd8d941 | ||
|
|
547079763e | ||
|
|
a7dfe04406 | ||
|
|
bf275a9097 | ||
|
|
507e58ed96 | ||
|
|
d9c0be408b | ||
|
|
5beb481145 | ||
|
|
7ef5172d80 | ||
|
|
e6812d7e36 | ||
|
|
75ce576d3d | ||
|
|
fa7cc57a6d | ||
|
|
fd2125ee94 | ||
|
|
52e622f1db | ||
|
|
2e3594c8bc | ||
|
|
3d7ac69c39 | ||
|
|
e379f8ec03 | ||
|
|
dbdf1cc296 | ||
|
|
dd14fdfdc5 | ||
|
|
fc6a567e0e | ||
|
|
96bd63cc4b | ||
|
|
169b172ffc | ||
|
|
b2b9c690f8 | ||
|
|
7a760a5135 | ||
|
|
ec67076090 | ||
|
|
9221b15bff | ||
|
|
a54333842f | ||
|
|
0c1f2720b3 | ||
|
|
75f7f1e9ba | ||
|
|
09fbf8e0ca | ||
|
|
d17d0d5f50 | ||
|
|
1a7a8486ca | ||
|
|
65548db916 | ||
|
|
894bb03b23 | ||
|
|
94573545f3 | ||
|
|
7734429b89 | ||
|
|
35f092afef | ||
|
|
b837bb7bdd | ||
|
|
c629a0c5ad | ||
|
|
d889322827 | ||
|
|
156dffb961 | ||
|
|
e5befc0a73 | ||
|
|
e3f6a6d916 | ||
|
|
58fecc8cbe | ||
|
|
b5aad9479e | ||
|
|
5db3a0e481 | ||
|
|
0300f2aa22 | ||
|
|
17d36a4cc3 | ||
|
|
c222f57b00 | ||
|
|
1b64508aab | ||
|
|
f2b92d4c7b | ||
|
|
82f82c7543 | ||
|
|
602623661a | ||
|
|
ca3564898d | ||
|
|
5b662b43a0 | ||
|
|
6ba6fc149a | ||
|
|
5a3a39aba4 | ||
|
|
b9b300fcbd | ||
|
|
59f52bce04 | ||
|
|
8d3465060d | ||
|
|
d0af08190e | ||
|
|
b343fcaba3 | ||
|
|
526099c928 | ||
|
|
f0984cf789 | ||
|
|
7be14d8155 | ||
|
|
28f6f034ff | ||
|
|
3be6083ea4 | ||
|
|
f367d0e707 | ||
|
|
9694a0f7ea | ||
|
|
04bfa545f7 | ||
|
|
1971ae8cac | ||
|
|
fd3d16d379 | ||
|
|
dfd406fe4c | ||
|
|
301c571405 | ||
|
|
3376d27915 | ||
|
|
0827646695 | ||
|
|
03578e66b5 | ||
|
|
71e24455a3 | ||
|
|
83a840656c | ||
|
|
ed54fff204 | ||
|
|
5d4f903482 | ||
|
|
946029c921 | ||
|
|
f4321f8624 | ||
|
|
46d05b1191 | ||
|
|
558e8ca312 | ||
|
|
b763d7d029 | ||
|
|
2d61639f90 | ||
|
|
204796868d | ||
|
|
37014e1002 | ||
|
|
c6c4657f83 | ||
|
|
f457394362 | ||
|
|
2b97c608f8 | ||
|
|
15493530f1 | ||
|
|
dd1d49b360 | ||
|
|
e9e8934577 | ||
|
|
2397e35cdd | ||
|
|
0e585d8102 | ||
|
|
6009934176 | ||
|
|
b20c2641d4 | ||
|
|
445a0dac37 | ||
|
|
33abe80b59 | ||
|
|
d7cf1c509b | ||
|
|
7d97f26870 | ||
|
|
b2107ba80b | ||
|
|
d0c431a2a3 | ||
|
|
ab7ef4ed3b | ||
|
|
204edb4a27 | ||
|
|
3c742d50b6 | ||
|
|
1c51cc34cd | ||
|
|
64b9b55a0d | ||
|
|
f9741b0728 | ||
|
|
3085254a91 | ||
|
|
0de35588c1 | ||
|
|
21ea1ac61e | ||
|
|
4fccaa514b | ||
|
|
13ad0c500b | ||
|
|
126a7f5c11 | ||
|
|
bb3bd76fe9 | ||
|
|
4bbdcdb0b8 | ||
|
|
d294a7f30f | ||
|
|
de8d0e35a2 | ||
|
|
faa84b5b85 | ||
|
|
e1e5f17b27 | ||
|
|
0e63000b5c | ||
|
|
151997b1e1 | ||
|
|
a36bcd33c6 | ||
|
|
9194fea915 | ||
|
|
67d9891926 | ||
|
|
05341fb3b3 | ||
|
|
c82afd7e54 | ||
|
|
ed98f2ca57 | ||
|
|
462e450bb3 | ||
|
|
06e5fcc010 | ||
|
|
ac84652e50 | ||
|
|
eee3980749 | ||
|
|
cf83fbe397 | ||
|
|
e221ff7cd4 | ||
|
|
607de16d82 | ||
|
|
d762627312 | ||
|
|
10dab495f2 | ||
|
|
ee1335b6a2 | ||
|
|
8687645c50 | ||
|
|
7b68fcd408 | ||
|
|
92dab0759c | ||
|
|
5c6e59f53c | ||
|
|
067fe27699 | ||
|
|
8db2ba9130 | ||
|
|
1500e9810c | ||
|
|
a3b21b10e4 | ||
|
|
fa03e98426 | ||
|
|
203dba271b | ||
|
|
91562ba934 | ||
|
|
fc5f7e0e85 | ||
|
|
a4123a069e | ||
|
|
a5ddb07cb3 | ||
|
|
917e101c2c | ||
|
|
5c624021ea | ||
|
|
5676a486cf | ||
|
|
1658feade8 | ||
|
|
5f1eceb1ee | ||
|
|
fc3491e0d0 | ||
|
|
9f94244994 | ||
|
|
6ebdd0cfd2 | ||
|
|
858377946f | ||
|
|
826d603b05 | ||
|
|
da4b761c45 | ||
|
|
70a2f8046c | ||
|
|
51bf95f6d1 | ||
|
|
2246f530af | ||
|
|
4e04ef0769 | ||
|
|
b2bbdf8cbf | ||
|
|
9178208ba8 | ||
|
|
7d3db0e5ed | ||
|
|
2869e5b4df | ||
|
|
510146eb6d | ||
|
|
c692d9e844 | ||
|
|
32423a83fc | ||
|
|
d50148591b | ||
|
|
b6451be582 | ||
|
|
5e296d7af8 | ||
|
|
3093a476b1 | ||
|
|
00e56c5155 | ||
|
|
8b9891aa8a | ||
|
|
f7901a2380 | ||
|
|
5c4352b57b | ||
|
|
9ca7c9631a | ||
|
|
d9e99d4688 | ||
|
|
3fd56b4038 | ||
|
|
44659df598 | ||
|
|
0e9ee239a9 | ||
|
|
ce0704a491 | ||
|
|
0acc1d8c78 | ||
|
|
18ef8962f1 | ||
|
|
e748be32da | ||
|
|
0ad14fc038 | ||
|
|
dd61439061 | ||
|
|
40bebf0c86 | ||
|
|
2aa5631e2e | ||
|
|
f39a0f8e40 | ||
|
|
ca19ffb083 | ||
|
|
15272f30f4 | ||
|
|
55176116a2 | ||
|
|
738de8cfa8 | ||
|
|
bd150ec658 | ||
|
|
ee21a604f3 | ||
|
|
43358157cf | ||
|
|
0b65d7555e | ||
|
|
8bc2abd367 | ||
|
|
6556881417 | ||
|
|
c54900f63e | ||
|
|
9c35189ad1 | ||
|
|
e998041229 | ||
|
|
431e1d5608 | ||
|
|
d4c7991aee | ||
|
|
811df48756 | ||
|
|
dbd9d99bcd | ||
|
|
c032743b93 | ||
|
|
418c1fc427 | ||
|
|
fe30279ed0 | ||
|
|
b4f096364f | ||
|
|
9e6a581f68 | ||
|
|
f7e49f3b25 | ||
|
|
2fd5efd92b | ||
|
|
67cf44e7c1 | ||
|
|
9ceaff7318 | ||
|
|
703c825196 | ||
|
|
86adcd6766 | ||
|
|
5a85c5e535 | ||
|
|
cf926338bf | ||
|
|
43930455de | ||
|
|
6f04bd9410 | ||
|
|
59212a538e | ||
|
|
a9b024330c | ||
|
|
d93761af62 | ||
|
|
fb6381fb35 | ||
|
|
1d65f81b16 | ||
|
|
1c40dde782 | ||
|
|
f6c4d2d161 | ||
|
|
b282a0f4f1 | ||
|
|
c1886c6513 | ||
|
|
bd8ecc1caa | ||
|
|
6bbcbc08cf | ||
|
|
f0a4ca5f69 | ||
|
|
de40842597 | ||
|
|
76ec746341 | ||
|
|
14102e8a48 | ||
|
|
4f2d8dfe72 | ||
|
|
7c60bb3e54 | ||
|
|
a62686622b | ||
|
|
a61f4df0b9 | ||
|
|
3266818b42 | ||
|
|
c9ecbaccb3 | ||
|
|
336a0facc1 | ||
|
|
7053f59ad1 | ||
|
|
3373572e15 | ||
|
|
1839bcf109 | ||
|
|
191c0dec32 | ||
|
|
2bc2b52eaa | ||
|
|
36a724feca | ||
|
|
18352090e7 | ||
|
|
4c97ffee34 | ||
|
|
ac5320e887 | ||
|
|
91b10bd37c | ||
|
|
79a2734068 | ||
|
|
32030687ba | ||
|
|
cb01363260 | ||
|
|
0493b27222 | ||
|
|
44d6b94752 | ||
|
|
a2bc7387e4 | ||
|
|
ea5e13893e | ||
|
|
bd044fc919 | ||
|
|
870a29d9b0 | ||
|
|
0e91febb9c | ||
|
|
37ddfa0521 | ||
|
|
5bd449c157 | ||
|
|
b69d7f0d2a | ||
|
|
a0475b3c29 | ||
|
|
3156458041 | ||
|
|
48333acba6 | ||
|
|
4a0456fb8e | ||
|
|
405be0f966 | ||
|
|
000928f9dc | ||
|
|
0f87e8ee87 | ||
|
|
2195a479a8 | ||
|
|
2383fd8813 | ||
|
|
d8b6d260c9 | ||
|
|
6a41ede2d4 | ||
|
|
c04081bc56 | ||
|
|
0b1ecd8872 | ||
|
|
88e90d5601 | ||
|
|
03464dc148 | ||
|
|
1112f1a003 | ||
|
|
c1576fcf97 | ||
|
|
8592eacbf9 | ||
|
|
888cb824d7 | ||
|
|
061527df6c | ||
|
|
96b0a0253f | ||
|
|
c79a59b599 | ||
|
|
fad7d58fc9 | ||
|
|
97efa84676 | ||
|
|
22347ea54d | ||
|
|
46513c6d78 | ||
|
|
1c7d01c2f4 | ||
|
|
7a0f2d71bb | ||
|
|
4104beadbb | ||
|
|
87f4b8be67 | ||
|
|
8d729d7da2 | ||
|
|
f016479289 | ||
|
|
c81cc2e6d5 | ||
|
|
f3aac85d01 | ||
|
|
c6665e3460 | ||
|
|
c7295b9e09 | ||
|
|
9fd9f712bf | ||
|
|
a9c70bcc1c | ||
|
|
80edd6ca87 | ||
|
|
48f46b568d | ||
|
|
279792f891 | ||
|
|
792b69ba11 | ||
|
|
06cff60bc1 | ||
|
|
770ec5946a | ||
|
|
b525a0c061 | ||
|
|
34970fd785 | ||
|
|
ceb5303581 | ||
|
|
f456f8fa8d | ||
|
|
e1fe13d0cb | ||
|
|
01511ea557 | ||
|
|
802241a660 | ||
|
|
e1535fbd71 | ||
|
|
aea8e16b4a | ||
|
|
0d6bb650cb | ||
|
|
ddc4ffffa0 | ||
|
|
d7a5f137ff | ||
|
|
34173638d4 | ||
|
|
c9618587ef | ||
|
|
101bfa3112 | ||
|
|
523bde4dc5 | ||
|
|
483350905b | ||
|
|
5b72334852 | ||
|
|
d13a37ce22 | ||
|
|
0c6f4b3bcc | ||
|
|
0e6fca4a38 | ||
|
|
dfd76be568 | ||
|
|
0dc08c2115 | ||
|
|
6b572b3f25 | ||
|
|
c6c40a5fb3 | ||
|
|
fdc6beed1a | ||
|
|
731aa8ead1 | ||
|
|
8762634cf1 | ||
|
|
735a91c9d5 | ||
|
|
705ce56694 | ||
|
|
94fdf2cf5d | ||
|
|
758c21fb9c | ||
|
|
15360056bd | ||
|
|
932c45a7ab | ||
|
|
e39743f2f8 | ||
|
|
cff4d53a9e | ||
|
|
c2ce1d00cd | ||
|
|
b3e0dc47a8 | ||
|
|
93f979ae18 | ||
|
|
ca3f871646 | ||
|
|
1be6c592a6 | ||
|
|
37cde3d864 | ||
|
|
2afd7186ae | ||
|
|
c19bf9cffe | ||
|
|
7e7579e1ba | ||
|
|
582359aeea | ||
|
|
6c3c643c8e | ||
|
|
3eaed5a122 | ||
|
|
4bb966a7f0 | ||
|
|
0e9e64c550 | ||
|
|
c5998fb483 | ||
|
|
880ada0a1c | ||
|
|
a5e5f53494 | ||
|
|
81f3a5c6cd | ||
|
|
59bee8df21 | ||
|
|
796837b8c7 | ||
|
|
2dc24fc234 | ||
|
|
88923f61a7 | ||
|
|
ba6fea1bf5 | ||
|
|
36d8ce8fab | ||
|
|
153fd9246e | ||
|
|
fac24d462f | ||
|
|
83101b878e | ||
|
|
9d1055b3d2 | ||
|
|
0614d30654 | ||
|
|
9965b6b9dd | ||
|
|
a06de4bc4f | ||
|
|
11a7cb5b73 | ||
|
|
bae6100ae8 | ||
|
|
3ffbb4d096 | ||
|
|
ca5d7bc683 | ||
|
|
1457850b72 | ||
|
|
100af48f53 | ||
|
|
3e211bf662 | ||
|
|
606d6b8fd4 | ||
|
|
b581c8cfc7 | ||
|
|
54d3134da2 | ||
|
|
259392035d | ||
|
|
4b81de93d3 | ||
|
|
93fc188afb | ||
|
|
007b75f78a | ||
|
|
0435216eb6 | ||
|
|
7061d2b25b | ||
|
|
31cdb4c8a7 | ||
|
|
1e76d84569 | ||
|
|
3204135a46 | ||
|
|
a64faf7bf7 | ||
|
|
4a79a718a3 | ||
|
|
e293f998a1 | ||
|
|
dbfaa81ee0 | ||
|
|
6012e94e50 | ||
|
|
0f67f7a782 | ||
|
|
4201ddaf4e | ||
|
|
14f1f8f53a | ||
|
|
61b5bd81d8 | ||
|
|
35306fa7f5 | ||
|
|
b441dcd6f0 | ||
|
|
17d368910f | ||
|
|
321e7e1175 | ||
|
|
bef3dd6760 | ||
|
|
3ded55f9f7 | ||
|
|
962cebf7c5 | ||
|
|
4081678f2e | ||
|
|
b202569c83 | ||
|
|
55a8339781 | ||
|
|
a6707f158b | ||
|
|
96a5fe9e15 | ||
|
|
24f523a351 | ||
|
|
065f8abfe3 | ||
|
|
7b5602d00a | ||
|
|
2bb7e15773 | ||
|
|
cb9cc5de5c | ||
|
|
0244123a52 | ||
|
|
1897bb3d2e | ||
|
|
b353e8a807 | ||
|
|
b3e2aca13a | ||
|
|
e829f8f71f | ||
|
|
9425e58591 | ||
|
|
603c9ef6a8 | ||
|
|
906b8f3f95 | ||
|
|
6cfa71a3c2 | ||
|
|
42f8d155f8 | ||
|
|
009c0b9200 | ||
|
|
c740373b31 | ||
|
|
03f92bb155 | ||
|
|
f8af93237a | ||
|
|
83029eb756 | ||
|
|
99c577e210 | ||
|
|
dd92335dc4 | ||
|
|
8c37499af8 | ||
|
|
a32276e400 | ||
|
|
83b8ad7a31 | ||
|
|
dfdf1f82ae | ||
|
|
cbda00c415 | ||
|
|
21dab3d7d8 | ||
|
|
9b399968eb | ||
|
|
df361e9dd6 | ||
|
|
245f501120 | ||
|
|
1902eafa8d | ||
|
|
7795968382 | ||
|
|
415192c001 | ||
|
|
580e8f0dbb | ||
|
|
095fccb974 | ||
|
|
ebff2bc7a3 | ||
|
|
a78f752143 | ||
|
|
a70d567ec6 | ||
|
|
8d259093bf | ||
|
|
0c6bbf275b | ||
|
|
824a2e0630 | ||
|
|
70a99cd1ee | ||
|
|
60a6665bbd | ||
|
|
2e5dae0c25 | ||
|
|
2d253fe1dc | ||
|
|
bb4788e997 | ||
|
|
510ced1d13 | ||
|
|
767391c26e | ||
|
|
6e805dda24 | ||
|
|
ea82dba555 | ||
|
|
2467c0e651 | ||
|
|
292dd238e7 | ||
|
|
b20a7c2beb | ||
|
|
de2832c0c0 | ||
|
|
d40704ab85 | ||
|
|
2cde6ff60f | ||
|
|
f586c58f96 | ||
|
|
84d4bbb13d | ||
|
|
071201e84b | ||
|
|
15d8200b13 | ||
|
|
d73c2b23e0 | ||
|
|
a808d48169 | ||
|
|
6ed829ff95 | ||
|
|
a52512863e | ||
|
|
4297b1ad55 | ||
|
|
b03f04ff24 | ||
|
|
86eeef1ccd | ||
|
|
ce2d7991c9 | ||
|
|
5d812949a1 | ||
|
|
855c82e224 | ||
|
|
955b472f8b | ||
|
|
c5612b34c9 | ||
|
|
9894e7e1fe | ||
|
|
7dd4576ee4 | ||
|
|
5fc2aad364 | ||
|
|
507ad5bac5 | ||
|
|
cd665be43e | ||
|
|
39c4414d5a | ||
|
|
a203bc5da9 | ||
|
|
36b61d2b11 | ||
|
|
2ce4530d24 | ||
|
|
84a7c2e67c | ||
|
|
c7d2760521 | ||
|
|
875782cc0a | ||
|
|
036e11c9ee | ||
|
|
b4c0661dce | ||
|
|
56dbec46db | ||
|
|
cfe3b75cb0 | ||
|
|
9415d839a5 | ||
|
|
4f7380c4d7 | ||
|
|
fd321cf07d | ||
|
|
12e1bb1daa | ||
|
|
a8866ab824 | ||
|
|
7534bfe2d9 |
4
.gitignore
vendored
@@ -5,15 +5,19 @@ node_modules
|
||||
static
|
||||
.grunt
|
||||
_SpecRunner.html
|
||||
__benchmarks__
|
||||
build/
|
||||
.module-cache
|
||||
*.gem
|
||||
docs/code
|
||||
docs/_site
|
||||
docs/.sass-cache
|
||||
docs/css/react.css
|
||||
docs/js/.module-cache
|
||||
docs/js/JSXTransformer.js
|
||||
docs/js/react.min.js
|
||||
docs/js/docs.js
|
||||
docs/js/jsx-compiler.js
|
||||
docs/js/live_editor.js
|
||||
docs/js/examples
|
||||
docs/downloads
|
||||
|
||||
14
.travis.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
language: node_js
|
||||
node_js:
|
||||
- '0.10'
|
||||
after_script:
|
||||
- curl -F "react=@build/react.js" -F "react.min=@build/react.min.js" -F "transformer=@build/JSXTransformer.js"
|
||||
-F "commit=$TRAVIS_COMMIT" -F "date=`git log --format='%ct' -1`" -F "pull_request=$TRAVIS_PULL_REQUEST"
|
||||
-F "token=$SECRET_TOKEN" -F "branch=$TRAVIS_BRANCH" $SERVER
|
||||
env:
|
||||
global:
|
||||
# SERVER
|
||||
- secure: qPvsJ46XzGrdIuPA70b55xQNGF8jcK7N1LN5CCQYYocXLa+fBrl+fTE77QvehOPhqwJXcj6kOxI+sY0KrVwV7gmq2XY2HZGWUSCxTN0SZlNIzqPA80Y7G/yOjA4PUt8LKgP+8tptyhTAY56qf+hgW8BoLiKOdztYF2p+3zXOLuA=
|
||||
# SECRET_TOKEN
|
||||
- secure: dkpPW+VnoqC/okhRdV90m36NcyBFhcwEKL3bNFExAwi0dXnFao8RoFlvnwiPlA23h2faROkMIetXlti6Aju08BgUFV+f9aL6vLyU7gUent4Nd3413zf2fwDtXIWIETg6uLnOpSykGKgCAT/hY3Q2oPLqOoY0OxfgnbqwxkxljrE=
|
||||
82
CHANGELOG.md
Normal file
@@ -0,0 +1,82 @@
|
||||
## 0.4.1 (July 26, 2013)
|
||||
|
||||
### React
|
||||
|
||||
* `setState` callbacks are now executed in the scope of your component.
|
||||
* `click` events now work on Mobile Safari.
|
||||
* Prevent a potential error in event handling if `Object.prototype` is extended.
|
||||
* Don't set DOM attributes to the string `"undefined"` on update when previously defined.
|
||||
* Improved support for `<iframe>` attributes.
|
||||
* Added checksums to detect and correct cases where server-side rendering markup mismatches what React expects client-side.
|
||||
|
||||
### JSXTransformer
|
||||
|
||||
* Improved environment detection so it can be run in a non-browser environment.
|
||||
|
||||
|
||||
## 0.4.0 (July 17, 2013)
|
||||
|
||||
### React
|
||||
|
||||
* Switch from using `id` attribute to `data-reactid` to track DOM nodes. This allows you to integrate with other JS and CSS libraries more easily.
|
||||
* Support for more DOM elements and attributes (e.g., `<canvas>`)
|
||||
* Improved server-side rendering APIs. `React.renderComponentToString(<component>, callback)` allows you to use React on the server and generate markup which can be sent down to the browser.
|
||||
* `prop` improvements: validation and default values. [Read our blog post for details...](http://facebook.github.io/react/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.html)
|
||||
* Support for the `key` prop, which allows for finer control over reconciliation. [Read the docs for details...](http://facebook.github.io/react/docs/multiple-components.html)
|
||||
* Removed `React.autoBind`. [Read our blog post for details...](http://facebook.github.io/react/blog/2013/07/02/react-v0-4-autobind-by-default.html)
|
||||
* Improvements to forms. We've written wrappers around `<input>`, `<textarea>`, `<option>`, and `<select>` in order to standardize many inconsistencies in browser implementations. This includes support for `defaultValue`, and improved implementation of the `onChange` event, and circuit completion. [Read the docs for details...](http://facebook.github.io/react/docs/forms.html)
|
||||
* We've implemented an improved synthetic event system that conforms to the W3C spec.
|
||||
* Updates to your component are batched now, which may result in a significantly faster re-render of components. `this.setState` now takes an optional callback as it's second parameter. If you were using `onClick={this.setState.bind(this, state)}` previously, you'll want to make sure you add a third parameter so that the event is not treated as the callback.
|
||||
|
||||
### JSX
|
||||
|
||||
* Support for comment nodes `<div>{/* this is a comment and won't be rendered */}</div>`
|
||||
* Children are now transformed directly into arguments instead of being wrapped in an array
|
||||
E.g. `<div><Component1/><Component2/></div>` is transformed into `React.DOM.div(null, Component1(null), Component2(null))`.
|
||||
Previously this would be transformed into `React.DOM.div(null, [Component1(null), Component2(null)])`.
|
||||
If you were using React without JSX previously, your code should still work.
|
||||
|
||||
### react-tools
|
||||
|
||||
* Fixed a number of bugs when transforming directories
|
||||
* No longer re-write `require()`s to be relative unless specified
|
||||
|
||||
|
||||
## 0.3.3 (June 20, 2013)
|
||||
|
||||
### React
|
||||
|
||||
* Allow reusing the same DOM node to render different components. e.g. `React.renderComponent(<div/>, domNode); React.renderComponent(<span/>, domNode);` will work now.
|
||||
|
||||
### JSX
|
||||
|
||||
* Improved the in-browser transformer so that transformed scripts will execute in the expected scope. The allows components to be defined and used from separate files.
|
||||
|
||||
### react-tools
|
||||
|
||||
* 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.
|
||||
|
||||
|
||||
## 0.3.2 (May 31, 2013)
|
||||
|
||||
### JSX
|
||||
|
||||
* Improved compatability with other coding styles (specifically, multiple assignments with a single `var`).
|
||||
|
||||
### react-tools
|
||||
|
||||
* Switch from using the browserified build to shipping individual modules. This allows react-tools to be used with [browserify](https://github.com/substack/node-browserify).
|
||||
|
||||
|
||||
## 0.3.1 (May 30, 2013)
|
||||
|
||||
### react-tools
|
||||
|
||||
* Fix bug in packaging resulting in broken module.
|
||||
|
||||
|
||||
## 0.3.0 (May 29, 2013)
|
||||
|
||||
* Initial public release
|
||||
14
Gruntfile.js
@@ -4,7 +4,9 @@ var exec = require('child_process').exec;
|
||||
var jsxTask = require('./grunt/tasks/jsx');
|
||||
var browserifyTask = require('./grunt/tasks/browserify');
|
||||
var wrapupTask = require('./grunt/tasks/wrapup');
|
||||
var populistTask = require('./grunt/tasks/populist');
|
||||
var phantomTask = require('./grunt/tasks/phantom');
|
||||
var npmTask = require('./grunt/tasks/npm');
|
||||
var releaseTasks = require('./grunt/tasks/release');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
@@ -15,7 +17,9 @@ module.exports = function(grunt) {
|
||||
jsx: require('./grunt/config/jsx/jsx'),
|
||||
browserify: require('./grunt/config/browserify'),
|
||||
wrapup: require('./grunt/config/wrapup'),
|
||||
populist: require('./grunt/config/populist'),
|
||||
phantom: require('./grunt/config/phantom'),
|
||||
npm: require('./grunt/config/npm'),
|
||||
clean: ['./build', './*.gem', './docs/_site', './examples/shared/*.js'],
|
||||
jshint: require('./grunt/config/jshint'),
|
||||
compare_size: require('./grunt/config/compare_size')
|
||||
@@ -42,18 +46,24 @@ module.exports = function(grunt) {
|
||||
// defines global variables instead of using require.
|
||||
grunt.registerMultiTask('wrapup', wrapupTask);
|
||||
|
||||
grunt.registerMultiTask('populist', populistTask);
|
||||
|
||||
grunt.registerMultiTask('phantom', phantomTask);
|
||||
|
||||
grunt.registerMultiTask('npm', npmTask);
|
||||
|
||||
grunt.registerTask('build:basic', ['jsx:debug', 'browserify:basic']);
|
||||
grunt.registerTask('build:transformer', ['jsx:debug', 'browserify:transformer']);
|
||||
grunt.registerTask('build:min', ['jsx:release', 'browserify:min']);
|
||||
grunt.registerTask('build:test', [
|
||||
'jsx:debug',
|
||||
'jsx:jasmine',
|
||||
'jsx:test',
|
||||
'browserify:test'
|
||||
'populist:jasmine',
|
||||
'populist:test'
|
||||
]);
|
||||
|
||||
grunt.registerTask('test', ['build:test', 'phantom:run']);
|
||||
grunt.registerTask('npm:test', ['build', 'npm:pack']);
|
||||
|
||||
// Optimized build task that does all of our builds. The subtasks will be run
|
||||
// in order so we can take advantage of that and only run jsx:debug once.
|
||||
|
||||
14
README.md
@@ -1,9 +1,9 @@
|
||||
# [React](http://facebook.github.io/react)
|
||||
# [React](http://facebook.github.io/react) [](https://travis-ci.org/facebook/react)
|
||||
|
||||
React is a JavaScript library for building user interfaces.
|
||||
|
||||
* **Declarative:** React uses a declarative paradigm that makes it easier to reason about your application.
|
||||
* **Efficient:** React minimizes interactions with the DOM by using a mock representation of the DOM.
|
||||
* **Efficient:** React computes the minimal set of changes necessary to keep your DOM up-to-date.
|
||||
* **Flexible:** React works with the libraries and frameworks that you already know.
|
||||
|
||||
[Learn how to use React in your own project.](http://facebook.github.io/react/docs/getting-started.html)
|
||||
@@ -32,21 +32,21 @@ You'll notice that we used an XML-like syntax; [we call it JSX](http://facebook.
|
||||
|
||||
## Installation
|
||||
|
||||
The fastest way to get started is to serve JavaScript from the CDN:
|
||||
The fastest way to get started is to serve JavaScript from the CDN (also available on [CDNJS](http://cdnjs.com/#react)):
|
||||
|
||||
```html
|
||||
<!-- The core React library -->
|
||||
<script src="http://fb.me/react-0.3.0.min.js"></script>
|
||||
<script src="http://fb.me/react-0.4.1.min.js"></script>
|
||||
<!-- In-browser JSX transformer, remove when pre-compiling JSX. -->
|
||||
<script src="http://fb.me/JSXTransformer-0.3.0.js"></script>
|
||||
<script src="http://fb.me/JSXTransformer-0.4.1.js"></script>
|
||||
```
|
||||
|
||||
We've also built a [starter kit](http://facebook.github.io/react/downloads/react-0.3.0.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](http://facebook.github.io/react/downloads/react-0.4.1.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:
|
||||
|
||||
```sh
|
||||
bower install react
|
||||
bower install --save react
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
31
bin/jsx
@@ -3,7 +3,7 @@
|
||||
|
||||
var visitors = require('../vendor/fbtransform/visitors').transformVisitors;
|
||||
var transform = require('../vendor/fbtransform/lib/transform').transform;
|
||||
var debranch = require("../vendor/woodchipper").debranch;
|
||||
var propagate = require("../vendor/constants").propagate;
|
||||
|
||||
require("commoner").resolve(function(id) {
|
||||
var context = this;
|
||||
@@ -25,18 +25,31 @@ require("commoner").resolve(function(id) {
|
||||
|
||||
}).process(function(id, source) {
|
||||
var context = this;
|
||||
var constants = context.config.constants || {};
|
||||
|
||||
// This is where JSX, ES6, etc. desugaring happens.
|
||||
source = transform(visitors.react, source).code;
|
||||
|
||||
return context.makePromise(function(callback) {
|
||||
var constants = context.config.constants || {};
|
||||
// Constant propagation means removing any obviously dead code after
|
||||
// replacing constant expressions with literal (boolean) values.
|
||||
source = propagate(constants, source);
|
||||
|
||||
// Debranching means removing any obviously dead code after
|
||||
// replacing constant conditional expressions with literal
|
||||
// (boolean) values.
|
||||
debranch(constants, source, function(source) {
|
||||
callback(null, source);
|
||||
if (context.config.mocking) {
|
||||
// Make sure there is exactly one newline at the end of the module.
|
||||
source = source.replace(/\s+$/m, "\n");
|
||||
|
||||
return context.getProvidedP().then(function(idToPath) {
|
||||
if (id !== "mock-modules" &&
|
||||
id !== "mocks" &&
|
||||
id !== "test/all" &&
|
||||
idToPath.hasOwnProperty("mock-modules")) {
|
||||
return source + '\nrequire("mock-modules").register(' +
|
||||
JSON.stringify(id) + ', module);\n';
|
||||
}
|
||||
|
||||
return source;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return source;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rake'
|
||||
|
||||
# jekyll, which builds it all
|
||||
gem 'jekyll', '~>1.0'
|
||||
|
||||
@@ -14,3 +16,6 @@ gem 'rb-fsevent'
|
||||
|
||||
# Redcarpet for Markdown
|
||||
gem 'redcarpet'
|
||||
|
||||
# For markdown header cleanup
|
||||
gem 'sanitize'
|
||||
|
||||
@@ -24,13 +24,19 @@ GEM
|
||||
liquid (2.5.0)
|
||||
maruku (0.6.1)
|
||||
syntax (>= 1.0.0)
|
||||
mini_portile (0.5.1)
|
||||
nokogiri (1.6.0)
|
||||
mini_portile (~> 0.5.0)
|
||||
posix-spawn (0.3.6)
|
||||
pygments.rb (0.5.0)
|
||||
posix-spawn (~> 0.3.6)
|
||||
yajl-ruby (~> 1.1.0)
|
||||
rake (10.0.4)
|
||||
rb-fsevent (0.9.3)
|
||||
redcarpet (2.2.2)
|
||||
safe_yaml (0.7.1)
|
||||
sanitize (2.0.6)
|
||||
nokogiri (>= 1.4.4)
|
||||
sass (3.2.9)
|
||||
syntax (1.0.0)
|
||||
yajl-ruby (1.1.0)
|
||||
@@ -41,6 +47,8 @@ PLATFORMS
|
||||
DEPENDENCIES
|
||||
jekyll (~> 1.0)
|
||||
json
|
||||
rake
|
||||
rb-fsevent
|
||||
redcarpet
|
||||
sanitize
|
||||
sass
|
||||
|
||||
@@ -13,7 +13,7 @@ task :js do
|
||||
end
|
||||
|
||||
desc "watch css & js"
|
||||
task :watch => [:update_version] do
|
||||
task :watch do
|
||||
Process.spawn "sass --style=compressed --watch _css/react.scss:css/react.css"
|
||||
Process.spawn "../bin/jsx --watch _js js"
|
||||
Process.waitall
|
||||
@@ -23,13 +23,15 @@ desc "update version to match ../package.json"
|
||||
task :update_version do
|
||||
react_version = JSON.parse(File.read('../package.json'))['version']
|
||||
site_config = YAML.load_file('_config.yml')
|
||||
site_config['react_version'] = react_version
|
||||
File.open('_config.yml', 'w+') { |f| f.write(site_config.to_yaml) }
|
||||
if site_config['react_version'] != react_version
|
||||
site_config['react_version'] = react_version
|
||||
File.open('_config.yml', 'w+') { |f| f.write(site_config.to_yaml) }
|
||||
end
|
||||
end
|
||||
|
||||
desc "build into ../../react-gh-pages"
|
||||
task :release => [:default] do
|
||||
task :release => [:update_version, :default] do
|
||||
system "jekyll build -d ../../react-gh-pages"
|
||||
end
|
||||
|
||||
task :default => [:update_version, :css, :js]
|
||||
task :default => [:css, :js]
|
||||
|
||||
@@ -1,14 +1,69 @@
|
||||
---
|
||||
name: React
|
||||
markdown: redcarpet
|
||||
---
|
||||
baseurl: /react
|
||||
react_version: 0.3.0
|
||||
redcarpet:
|
||||
extensions:
|
||||
- fenced_code_blocks
|
||||
pygments: true
|
||||
exclude:
|
||||
url: http://facebook.github.io
|
||||
permalink: /blog/:year/:month/:day/:title.html
|
||||
exclude:
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- README.md
|
||||
- Rakefile
|
||||
redcarpet:
|
||||
extensions:
|
||||
- fenced_code_blocks
|
||||
pygments: true
|
||||
name: React
|
||||
markdown: redcarpet
|
||||
react_version: 0.4.2
|
||||
description: A JavaScript library for building user interfaces
|
||||
relative_permalinks: true
|
||||
paginate: 5
|
||||
paginate_path: /blog/page:num
|
||||
nav_docs_sections:
|
||||
- title: Quick Start
|
||||
items:
|
||||
- id: getting-started
|
||||
title: Getting Started
|
||||
- id: tutorial
|
||||
title: Tutorial
|
||||
- title: Guides
|
||||
items:
|
||||
- id: why-react
|
||||
title: Why React?
|
||||
- id: displaying-data
|
||||
title: Displaying Data
|
||||
subitems:
|
||||
- id: jsx-in-depth
|
||||
title: JSX in Depth
|
||||
- id: jsx-gotchas
|
||||
title: JSX Gotchas
|
||||
- id: interactivity-and-dynamic-uis
|
||||
title: Interactivity and Dynamic UIs
|
||||
- id: multiple-components
|
||||
title: Multiple Components
|
||||
- id: reusable-components
|
||||
title: Reusable Components
|
||||
- id: forms
|
||||
title: Forms
|
||||
- id: working-with-the-browser
|
||||
title: Working With the Browser
|
||||
subitems:
|
||||
- id: more-about-refs
|
||||
title: More About Refs
|
||||
- id: tooling-integration
|
||||
title: Tooling Integration
|
||||
- id: examples
|
||||
title: Examples
|
||||
- title: Reference
|
||||
items:
|
||||
- id: top-level-api
|
||||
title: Top-Level API
|
||||
- id: component-api
|
||||
title: Component API
|
||||
- id: component-specs
|
||||
title: Component Specs and Lifecycle
|
||||
- id: tags-and-attributes
|
||||
title: Supported Tags and Attributes
|
||||
- id: events
|
||||
title: Event System
|
||||
- id: dom-differences
|
||||
title: DOM Differences
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
@import '_typography';
|
||||
@import '_solarized';
|
||||
|
||||
@mixin code-typography {
|
||||
font-family: 'source-code-pro', Menlo, 'Courier New', Consolas, monospace;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
$skinnyContentWidth: 650px;
|
||||
$contentWidth: 920px;
|
||||
$contentPadding: 20px;
|
||||
@@ -193,13 +199,15 @@ li {
|
||||
font-size: 14px;
|
||||
// position: fixed;
|
||||
float: left;
|
||||
top: 100px;
|
||||
width: 180px;
|
||||
width: 210px;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
ul ul {
|
||||
margin-left: 20px;
|
||||
}
|
||||
li {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -239,6 +247,12 @@ li {
|
||||
|
||||
}
|
||||
|
||||
.nav-blog {
|
||||
li {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
// Home Page specifics
|
||||
|
||||
.home-section {
|
||||
@@ -276,14 +290,14 @@ li {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#examples {
|
||||
h3 {
|
||||
color: $darkColor;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#examples h3, .home-presentation h3 {
|
||||
color: $darkColor;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#examples {
|
||||
p {
|
||||
margin: 0 0 25px 0;
|
||||
max-width: $twoColumnWidth;
|
||||
@@ -350,6 +364,22 @@ section.black content {
|
||||
padding-bottom: 18px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blog
|
||||
*/
|
||||
|
||||
.blogContent {
|
||||
padding-top: 20px;
|
||||
|
||||
blockquote {
|
||||
padding: 5px 15px;
|
||||
margin: 20px 0;
|
||||
background-color: #f8f5ec;
|
||||
border-left: 5px solid #f7ebc6;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Docs
|
||||
*/
|
||||
@@ -396,6 +426,26 @@ section.black content {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
/* JSX Compiler */
|
||||
|
||||
.jsxCompiler {
|
||||
margin: 0 auto;
|
||||
padding-top: 20px;
|
||||
width: 1220px;
|
||||
|
||||
#jsxCompiler {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.playgroundPreview {
|
||||
padding: 14px;
|
||||
width: 600px;
|
||||
|
||||
pre {
|
||||
@include code-typography;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Button */
|
||||
|
||||
@@ -469,6 +519,10 @@ p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
figure {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.inner-content {
|
||||
float: right;
|
||||
width: $skinnyContentWidth;
|
||||
@@ -479,12 +533,16 @@ p {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Blog */
|
||||
|
||||
.post-list-item + .post-list-item {
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
/* Code Mirror */
|
||||
|
||||
div.CodeMirror pre, div.CodeMirror-linenumber, code {
|
||||
font-family: 'source-code-pro', Menlo, 'Courier New', Consolas, monospace;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
@include code-typography;
|
||||
}
|
||||
|
||||
div.CodeMirror-linenumber:after {
|
||||
@@ -628,3 +686,19 @@ p code {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.post {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-bottom: 30px;
|
||||
|
||||
/* Trick to get the wrapper to expand to fit floating elements */
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.next {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
10
docs/_includes/blog_post.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<h1><a href="/react{{ page.url }}">{{ page.title }}</a></h1>
|
||||
<p class="meta">{{ page.date | date_to_string }} by {{ page.author }}</p>
|
||||
|
||||
<div id="post">
|
||||
{% if content != '' %}
|
||||
{{ page.excerpt }}
|
||||
{% else %}
|
||||
{{ page.content }}
|
||||
{% endif %}
|
||||
</div>
|
||||
11
docs/_includes/nav_blog.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<div class="nav-docs nav-blog">
|
||||
<div class="nav-docs-section">
|
||||
<h3>Recent posts</h3>
|
||||
<ul>
|
||||
{% for post in site.posts limit:10 %}
|
||||
<li><a href="/react{{ post.url }}"{% if page.title == post.title %} class="active"{% endif %}>{{ post.title }}</a></li>
|
||||
{% endfor %}
|
||||
<li><a href="/react/blog/all.html">All posts ...</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,23 +1,27 @@
|
||||
<div class="nav-docs">
|
||||
<div class="nav-docs-section">
|
||||
<h3>Getting started</h3>
|
||||
<ul>
|
||||
<li><a href="/react/docs/getting-started.html"{% if page.id == 'docs-getting-started' %} class="active"{% endif %}>Getting Started</a></li>
|
||||
<li><a href="/react/docs/tutorial.html"{% if page.id == 'docs-tutorial' %} class="active"{% endif %}>Tutorial</a></li>
|
||||
<li><a href="/react/docs/common-questions.html"{% if page.id == 'docs-common-questions' %} class="active"{% endif %}>Common Questions</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="nav-docs-section">
|
||||
<h3>Reference</h3>
|
||||
<ul>
|
||||
<li><a href="/react/docs/syntax.html"{% if page.id == 'docs-syntax' %} class="active"{% endif %}>JSX Syntax</a></li>
|
||||
<li><a href="/react/docs/component-basics.html"{% if page.id == 'docs-component-basics' %} class="active"{% endif %}>Component Basics</a></li>
|
||||
<li><a href="/react/docs/component-data.html"{% if page.id == 'docs-component-data' %} class="active"{% endif %}>Component Data</a></li>
|
||||
<li><a href="/react/docs/component-lifecycle.html"{% if page.id == 'docs-component-lifecycle' %} class="active"{% endif %}>Component Lifecycle</a></li>
|
||||
<li><a href="/react/docs/event-handling.html"{% if page.id == 'docs-event-handling' %} class="active"{% endif %}>Event Handling</a></li>
|
||||
<li><a href="/react/docs/advanced-components.html"{% if page.id == 'docs-advanced-components' %} class="active"{% endif %}>Advanced Components</a></li>
|
||||
<li><a href="/react/docs/api.html"{% if page.id == 'docs-api' %} class="active"{% endif %}>API</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% for section in site.nav_docs_sections %}
|
||||
<div class="nav-docs-section">
|
||||
<h3>{{ section.title }}</h3>
|
||||
<ul>
|
||||
{% for item in section.items %}
|
||||
<li>
|
||||
<a href="/react/docs/{{ item.id }}.html"{% if page.id == item.id %} class="active"{% endif %}>
|
||||
{{ item.title }}
|
||||
</a>
|
||||
{% if item.subitems %}
|
||||
<ul>
|
||||
{% for subitem in item.subitems %}
|
||||
<li>
|
||||
<a href="/react/docs/{{ subitem.id }}.html"{% if page.id == subitem.id %} class="active"{% endif %}>
|
||||
{{ subitem.title }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -11,16 +11,17 @@ var MarkdownEditor = React.createClass({\n\
|
||||
getInitialState: function() {\n\
|
||||
return {value: 'Type some *markdown* here!'};\n\
|
||||
},\n\
|
||||
handleKeyUp: React.autoBind(function() {\n\
|
||||
handleChange: function() {\n\
|
||||
this.setState({value: this.refs.textarea.getDOMNode().value});\n\
|
||||
}),\n\
|
||||
},\n\
|
||||
render: function() {\n\
|
||||
return (\n\
|
||||
<div className=\"MarkdownEditor\">\n\
|
||||
<h3>Input</h3>\n\
|
||||
<textarea onKeyUp={this.handleKeyUp} ref=\"textarea\">\n\
|
||||
{this.state.value}\n\
|
||||
</textarea>\n\
|
||||
<textarea\n\
|
||||
onChange={this.handleChange}\n\
|
||||
ref=\"textarea\"\n\
|
||||
defaultValue={this.state.value} />\n\
|
||||
<h3>Output</h3>\n\
|
||||
<div\n\
|
||||
className=\"content\"\n\
|
||||
|
||||
@@ -3,27 +3,27 @@
|
||||
*/
|
||||
|
||||
var TIMER_COMPONENT = "\
|
||||
/** @jsx React.DOM */\n\
|
||||
var Timer = React.createClass({\n\
|
||||
getInitialState: function() {\n\
|
||||
return {secondsElapsed: 0};\n\
|
||||
},\n\
|
||||
tick: React.autoBind(function() {\n\
|
||||
tick: function() {\n\
|
||||
this.setState({secondsElapsed: this.state.secondsElapsed + 1});\n\
|
||||
}),\n\
|
||||
},\n\
|
||||
componentDidMount: function() {\n\
|
||||
setInterval(this.tick, 1000);\n\
|
||||
this.interval = setInterval(this.tick, 1000);\n\
|
||||
},\n\
|
||||
componentWillUnmount: function() {\n\
|
||||
clearInterval(this.interval);\n\
|
||||
},\n\
|
||||
render: function() {\n\
|
||||
return (\n\
|
||||
<div>\n\
|
||||
{'Seconds Elapsed: ' + this.state.secondsElapsed}\n\
|
||||
</div>\n\
|
||||
return React.DOM.div({},\n\
|
||||
'Seconds Elapsed: ' + this.state.secondsElapsed\n\
|
||||
);\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
React.renderComponent(<Timer />, mountNode);\
|
||||
React.renderComponent(Timer({}), mountNode);\
|
||||
";
|
||||
|
||||
React.renderComponent(
|
||||
|
||||
@@ -6,48 +6,38 @@ var TODO_COMPONENT = "\
|
||||
/** @jsx React.DOM */\n\
|
||||
var TodoList = React.createClass({\n\
|
||||
render: function() {\n\
|
||||
var items = this.props.items.map(function(item) {\n\
|
||||
return <li>{item}</li>;\n\
|
||||
});\n\
|
||||
return <ul>{items}</ul>;\n\
|
||||
var createItem = function(itemText) {\n\
|
||||
return <li>{itemText}</li>;\n\
|
||||
};\n\
|
||||
return <ul>{this.props.items.map(createItem)}</ul>;\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
var TodoCreate = React.createClass({\n\
|
||||
handleSubmit: function() {\n\
|
||||
var textInput = this.refs.textInput.getDOMNode();\n\
|
||||
this.props.onCreate(textInput.value);\n\
|
||||
textInput.value = '';\n\
|
||||
return false;\n\
|
||||
},\n\
|
||||
render: function() {\n\
|
||||
return (\n\
|
||||
<form onSubmit={this.handleSubmit.bind(this)}>\n\
|
||||
<input type=\"text\" ref=\"textInput\" />\n\
|
||||
<button>Add</button>\n\
|
||||
</form>\n\
|
||||
);\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
var TodoApp = React.createClass({\n\
|
||||
getInitialState: function() {\n\
|
||||
return {items: []};\n\
|
||||
return {items: [], text: ''};\n\
|
||||
},\n\
|
||||
onItemCreate: function(value) {\n\
|
||||
this.setState({items: this.state.items.concat([value])});\n\
|
||||
onChange: function(e) {\n\
|
||||
this.setState({text: e.target.value});\n\
|
||||
},\n\
|
||||
handleSubmit: function(e) {\n\
|
||||
e.preventDefault();\n\
|
||||
var nextItems = this.state.items.concat([this.state.text]);\n\
|
||||
var nextText = '';\n\
|
||||
this.setState({items: nextItems, text: nextText});\n\
|
||||
},\n\
|
||||
render: function() {\n\
|
||||
return (\n\
|
||||
<div>\n\
|
||||
<h3>TODO</h3>\n\
|
||||
<TodoList items={this.state.items} />\n\
|
||||
<TodoCreate onCreate={this.onItemCreate.bind(this)} />\n\
|
||||
<form onSubmit={this.handleSubmit}>\n\
|
||||
<input onChange={this.onChange} value={this.state.text} />\n\
|
||||
<button>{'Add #' + (this.state.items.length + 1)}</button>\n\
|
||||
</form>\n\
|
||||
</div>\n\
|
||||
);\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
React.renderComponent(<TodoApp />, mountNode);\
|
||||
";
|
||||
|
||||
|
||||
19
docs/_js/jsx-compiler.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
var HELLO_COMPONENT = "\
|
||||
/** @jsx React.DOM */\n\
|
||||
var HelloMessage = React.createClass({\n\
|
||||
render: function() {\n\
|
||||
return <div>{'Hello ' + this.props.name}</div>;\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
React.renderComponent(<HelloMessage name=\"John\" />, mountNode);\
|
||||
";
|
||||
|
||||
React.renderComponent(
|
||||
<ReactPlayground codeText={HELLO_COMPONENT} renderCode={true} />,
|
||||
document.getElementById('jsxCompiler')
|
||||
);
|
||||
@@ -24,7 +24,7 @@ var CodeMirrorEditor = React.createClass({
|
||||
matchBrackets: true,
|
||||
theme: 'solarized-light'
|
||||
});
|
||||
this.editor.on('change', this.onChange.bind(this));
|
||||
this.editor.on('change', this.onChange);
|
||||
this.onChange();
|
||||
},
|
||||
onChange: function() {
|
||||
@@ -40,7 +40,7 @@ var CodeMirrorEditor = React.createClass({
|
||||
if (IS_MOBILE) {
|
||||
editor = <pre style={{overflow: 'scroll'}}>{this.props.codeText}</pre>;
|
||||
} else {
|
||||
editor = <textarea ref="editor">{this.props.codeText}</textarea>;
|
||||
editor = <textarea ref="editor" defaultValue={this.props.codeText} />;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -81,7 +81,7 @@ var ReactPlayground = React.createClass({
|
||||
/>;
|
||||
} else if (this.state.mode === this.MODES.JS) {
|
||||
content =
|
||||
<div class={{playgroundJS: true, playgroundStage: true}}>
|
||||
<div class="playgroundJS playgroundStage">
|
||||
{this.getDesugaredCode()}
|
||||
</div>;
|
||||
}
|
||||
@@ -111,9 +111,19 @@ var ReactPlayground = React.createClass({
|
||||
} catch (e) { }
|
||||
|
||||
try {
|
||||
eval(this.getDesugaredCode());
|
||||
if (this.props.renderCode) {
|
||||
React.renderComponent(
|
||||
<pre>{this.getDesugaredCode()}</pre>,
|
||||
mountNode
|
||||
);
|
||||
} else {
|
||||
eval(this.getDesugaredCode());
|
||||
}
|
||||
} catch (e) {
|
||||
React.renderComponent(<div content={e.toString()} class={{playgroundError: true}} />, mountNode);
|
||||
React.renderComponent(
|
||||
<div content={e.toString()} class="playgroundError" />,
|
||||
mountNode
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
<meta property="og:url" content="http://facebook.github.io/react{{ page.url }}" />
|
||||
<meta property="og:image" content="http://facebook.github.io/react/img/logo_og.png" />
|
||||
<meta property="og:description" content="A JavaScript library for building user interfaces" />
|
||||
<meta property="fb:app_id" content="623268441017527" />
|
||||
|
||||
<link rel="shortcut icon" href="/react/favicon.ico">
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ site.name }}" href="{{ site.url }}{{ site.baseurl }}/feed.xml">
|
||||
|
||||
<link rel="stylesheet" href="/react/css/react.css">
|
||||
<link rel="stylesheet" href="/react/css/syntax.css">
|
||||
@@ -34,13 +36,14 @@
|
||||
<div class="nav-main">
|
||||
<div class="wrap">
|
||||
<a class="nav-home" href="/react/index.html">
|
||||
<img class="nav-logo" alt="" src="/react/img/logo_small.png">
|
||||
<img class="nav-logo" alt="" src="/react/img/logo_small.png" width="38" height="38">
|
||||
React
|
||||
</a>
|
||||
<ul class="nav-site">
|
||||
<li><a href="/react/docs/getting-started.html"{% if page.sectionid == 'docs' %} 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>
|
||||
<li><a href="http://github.com/facebook/react">github</a>
|
||||
</ul>
|
||||
<!-- <iframe src="http://ghbtns.com/github-btn.html?user=facebook&repo=react.js&type=fork"allowtransparency="true" frameborder="0" scrolling="0" width="62" height="20"></iframe> -->
|
||||
@@ -70,6 +73,7 @@
|
||||
<div class="right">© 2013 Facebook Inc.</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div id="fb-root"></div>
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
@@ -77,7 +81,16 @@
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-41298772-1', 'facebook.github.io');
|
||||
ga('send', 'pageview');
|
||||
|
||||
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
|
||||
|
||||
(function(d, s, id) {
|
||||
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";
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}(document, 'script', 'facebook-jssdk'));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -19,5 +19,7 @@ sectionid: docs
|
||||
<a class="docs-next" href="/react/docs/{{ page.next }}">Next →</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="fb-comments" data-width="650" data-num-posts="10" data-href="{{ site.url }}{{ site.baseurl }}{{ page.url }}"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
---
|
||||
layout: default
|
||||
sectionid: blog
|
||||
---
|
||||
|
||||
<section class="content wrap">
|
||||
<h2>{{ page.title }}</h2>
|
||||
<p class="meta">{{ page.date | date_to_string }}</p>
|
||||
<section class="content wrap blogContent">
|
||||
{% include nav_blog.html %}
|
||||
<div class="inner-content">
|
||||
<h1>{{ page.title }}</h1>
|
||||
<p class="meta">{{ page.date | date: "%B %e, %Y" }} by {{ page.author }}</p>
|
||||
|
||||
<div id="post">
|
||||
{{ content }}
|
||||
<hr>
|
||||
|
||||
<div class="post">
|
||||
{{ content }}
|
||||
</div>
|
||||
|
||||
<div class="fb-like" data-send="true" data-width="650" data-show-faces="false"></div>
|
||||
<div class="fb-comments" data-width="650" data-num-posts="10" data-href="{{ site.url }}{{ site.baseurl }}{{ page.url }}"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
6
docs/_layouts/redirect.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; {{ page.destination }}">
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
17
docs/_plugins/header_links.rb
Normal file
@@ -0,0 +1,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).
|
||||
|
||||
class Redcarpet::Render::HTML
|
||||
def header(title, level)
|
||||
clean_title = Sanitize.clean(title)
|
||||
.downcase
|
||||
.gsub(/\s+/, "-")
|
||||
.gsub(/[^A-Za-z0-9\-_.]/, "")
|
||||
|
||||
return "<h#{level} id=\"#{clean_title}\">#{title}</h#{level}>"
|
||||
end
|
||||
end
|
||||
|
||||
11
docs/_posts/2013-06-02-jsfiddle-integration.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: JSFiddle Integration
|
||||
layout: post
|
||||
author: Christopher Chedeau
|
||||
---
|
||||
|
||||
[JSFiddle](http://jsfiddle.net) just announced support for React. This is an exciting news as it makes collaboration on snippets of code a lot easier. You can play around this **[base React JSFiddle](http://jsfiddle.net/vjeux/kb3gN/)**, fork it and share it! A [fiddle without JSX](http://jsfiddle.net/vjeux/VkebS/) is also available.
|
||||
|
||||
|
||||
<blockquote class="twitter-tweet" align="center"><p>React (by Facebook) is now available on JSFiddle. <a href="http://t.co/wNQf9JPv5u" title="http://facebook.github.io/react/">facebook.github.io/react/</a></p>— JSFiddle (@jsfiddle) <a href="https://twitter.com/jsfiddle/status/341114115781177344">June 2, 2013</a></blockquote>
|
||||
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||
91
docs/_posts/2013-06-05-why-react.md
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
title: Why did we build React?
|
||||
layout: post
|
||||
author: Pete Hunt
|
||||
---
|
||||
|
||||
There are a lot of JavaScript MVC frameworks out there. Why did we build React
|
||||
and why would you want to use it?
|
||||
|
||||
## React isn't an MVC framework.
|
||||
|
||||
React is a library for building composable user interfaces. It encourages
|
||||
the creation of reusable UI components which present data that changes over
|
||||
time.
|
||||
|
||||
## React doesn't use templates.
|
||||
|
||||
Traditionally, web application UIs are built using templates or HTML directives.
|
||||
These templates dictate the full set of abstractions that you are allowed to use
|
||||
to build your UI.
|
||||
|
||||
React approaches building user interfaces differently by breaking them into
|
||||
**components**. This means React uses a real, full featured programming language
|
||||
to render views, which we see as an advantage over templates for a few reasons:
|
||||
|
||||
- **JavaScript is a flexible, powerful programming language** with the ability
|
||||
to build abstractions. This is incredibly important in large applications.
|
||||
- By unifying your markup with its corresponding view logic, React can actually
|
||||
make views **easier to extend and maintain**.
|
||||
- By baking an understanding of markup and content into JavaScript, there's
|
||||
**no manual string concatenation** and therefore less surface area for XSS
|
||||
vulnerabilities.
|
||||
|
||||
We've also created [JSX](http://facebook.github.io/react/docs/syntax.html), an optional
|
||||
syntax extension, in case you prefer the readability of HTML to raw JavaScript.
|
||||
|
||||
## Reactive updates are dead simple.
|
||||
|
||||
React really shines when your data changes over time.
|
||||
|
||||
In a traditional JavaScript application, you need to look at what data changed
|
||||
and imperatively make changes to the DOM to keep it up-to-date. Even AngularJS,
|
||||
which provides a declarative interface via directives and data binding [requires
|
||||
a linking function to manually update DOM nodes](http://docs.angularjs.org/guide/directive#reasonsbehindthecompilelinkseparation).
|
||||
|
||||
React takes a different approach.
|
||||
|
||||
When your component is first initialized, the `render` method is called,
|
||||
generating a lightweight representation of your view. From that representation,
|
||||
a string of markup is produced, and injected into the document. When your data
|
||||
changes, the `render` method is called again. In order to perform updates as
|
||||
efficiently as possible, we diff the return value from the previous call to
|
||||
`render` with the new one, and generate a minimal set of changes to be applied
|
||||
to the DOM.
|
||||
|
||||
> The data returned from `render` is neither a string nor a DOM node -- it's a
|
||||
> 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
|
||||
reconciliation in action.
|
||||
|
||||
Because this re-render is so fast (around 1ms for TodoMVC), the developer
|
||||
doesn't need to explicitly specify data bindings. We've found this approach
|
||||
makes it easier to build apps.
|
||||
|
||||
## HTML is just the beginning.
|
||||
|
||||
Because React has its own lightweight representation of the document, we can do
|
||||
some pretty cool things with it:
|
||||
|
||||
- Facebook has dynamic charts that render to `<canvas>` instead of HTML.
|
||||
- Instagram is a "single page" web app built entirely with React and
|
||||
`Backbone.Router`. Designers regularly contribute React code with JSX.
|
||||
- We've built internal prototypes that run React apps in a web worker and use
|
||||
React to drive **native iOS views** via an Objective-C bridge.
|
||||
- You can run React
|
||||
[on the server](http://github.com/petehunt/react-server-rendering)
|
||||
for SEO, performance, code sharing and overall flexibility.
|
||||
- Events behave in a consistent, standards-compliant way in all browsers
|
||||
(including IE8) and automatically use
|
||||
[event delegation](http://davidwalsh.name/event-delegate).
|
||||
|
||||
Head on over to
|
||||
[facebook.github.io/react](http://facebook.github.io/react) to check
|
||||
out what we have built. Our documentation is geared towards building
|
||||
apps with the framework, but if you are interested in the
|
||||
nuts and bolts
|
||||
[get in touch](http://facebook.github.io/react/support.html) with us!
|
||||
|
||||
Thanks for reading!
|
||||
48
docs/_posts/2013-06-12-community-roundup.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "Community Round-up #1"
|
||||
layout: post
|
||||
author: Vjeux
|
||||
---
|
||||
|
||||
React was open sourced two weeks ago and it's time for a little round-up of what has been going on.
|
||||
|
||||
## Khan Academy Question Editor
|
||||
|
||||
It looks like [Ben Alpert](http://benalpert.com/) is the first person outside of Facebook and Instagram to push React code to production. We are very grateful for his contributions in form of pull requests, bug reports and presence on IRC ([#reactjs on Freenode](irc://chat.freenode.net/reactjs)). Ben wrote about his experience using React:
|
||||
|
||||
> I just rewrote a 2000-line project in React and have now made a handful of pull requests to React. Everything about React I've seen so far seems really well thought-out and I'm proud to be the first non-FB/IG production user of React.
|
||||
>
|
||||
> The project that I rewrote in React (and am continuing to improve) is the Khan Academy question editor which content creators can use to enter questions and hints that will be presented to students:
|
||||
> <figure>[](http://benalpert.com/2013/06/09/using-react-to-speed-up-khan-academy.html)</figure>
|
||||
>
|
||||
> [Read the full post...](http://benalpert.com/2013/06/09/using-react-to-speed-up-khan-academy.html)
|
||||
|
||||
## Pimp my Backbone.View (by replacing it with React)
|
||||
|
||||
[Paul Seiffert](https://blog.mayflower.de/) wrote a blog post that explains how to integrate React into Backbone applications.
|
||||
|
||||
> React has some interesting concepts for JavaScript view objects that can be used to eliminate this one big problem I have with Backbone.js.
|
||||
>
|
||||
> As in most MVC implementations (although React is probably just a VC implementation), a view is one portion of the screen that is managed by a controlling object. This object is responsible for deciding when to re-render the view and how to react to user input. With React, these view-controllers objects are called components. A component knows how to render its view and how to handle to the user's interaction with it.
|
||||
>
|
||||
> The interesting thing is that React is figuring out by itself when to re-render a view and how to do this in the most efficient way.
|
||||
>
|
||||
> [Read the full post...](https://blog.mayflower.de/3937-Backbone-React.html)
|
||||
|
||||
## Using facebook's React with require.js
|
||||
|
||||
[Mario Mueller](http://blog.xenji.com/) wrote a menu component in React and was able to easily integrate it with require.js, EventEmitter2 and bower.
|
||||
|
||||
> I recently stumbled upon facebook's React library, which is a Javascript library for building reusable frontend components. Even if this lib is only at version 0.3.x it behaves very stable, it is fast and is fun to code. I'm a big fan of require.js, so I tried to use React within the require.js eco system. It was not as hard as expected and here are some examples and some thoughts about it.
|
||||
>
|
||||
> [Read the full post...](http://blog.xenji.com/2013/06/facebooks-react-require-js.html)
|
||||
|
||||
## Origins of React
|
||||
|
||||
[Pete Hunt](http://www.petehunt.net/blog/) explained what differentiates React from other JavaScript libraries in [a previous blog post](http://facebook.github.io/react/blog/2013/06/05/why-react.html). [Lee Byron](http://leebyron.com/) gives another perspective on Quora:
|
||||
|
||||
> React isn't quite like any other popular Javascript libraries, and it solves a very specific problem: complex UI rendering. It's also intended to be used along side many other popular libraries. For example, React works well with Backbone.js, amongst many others.
|
||||
>
|
||||
> React was born out of frustrations with the common pattern of writing two-way data bindings in complex MVC apps. React is an implementation of one-way data bindings.
|
||||
>
|
||||
> [Read the full post...](http://www.quora.com/React-JS-Library/How-is-Facebooks-React-JavaScript-library/answer/Lee-Byron?srid=3DcX)
|
||||
71
docs/_posts/2013-06-19-community-roundup-2.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: "Community Round-up #2"
|
||||
layout: post
|
||||
author: Vjeux
|
||||
---
|
||||
|
||||
Since the launch we have received a lot of feedback and are actively working on React 0.4. In the meantime, here are the highlights of this week.
|
||||
|
||||
## Some quick thoughts on React
|
||||
|
||||
[Andrew Greig](http://www.andrewgreig.com/) made a blog post that gives a high level description of what React is.
|
||||
|
||||
> I have been using Facebooks recently released Javascript framework called React.js for the last few days and have managed to obtain a rather high level understanding of how it works and formed a good perspective on how it fits in to the entire javascript framework ecosystem.
|
||||
>
|
||||
> Basically, React is not an MVC framework. It is not a replacement for Backbone or Knockout or Angular, instead it is designed to work with existing frameworks and help extend their functionality.
|
||||
>
|
||||
> It is designed for building big UIs. The type where you have lots of reusable components that are handling events and presenting and changing some backend data. In a traditional MVC app, React fulfils the role of the View. So you would still need to handle the Model and Controller on your own.
|
||||
>
|
||||
> I found the best way to utilise React was to pair it with Backbone, with React replacing the Backbone View, or to write your own Model/Data object and have React communicate with that.
|
||||
>
|
||||
> [Read the full post...](http://www.andrewgreig.com/637/)
|
||||
|
||||
## React and Socket.IO Chat Application
|
||||
|
||||
[Danial Khosravi](http://danialk.github.io/) made a real-time chat application that interacts with the back-end using Socket.IO.
|
||||
|
||||
> A week ago I was playing with AngularJS and [this little chat application](https://github.com/btford/angular-socket-io-im) which uses socket.io and nodejs for realtime communication. Yesterday I saw a post about ReactJS in [EchoJS](http://www.echojs.com/) and started playing with this UI library. After playing a bit with React, I decided to write and chat application using React and I used Bran Ford's Backend for server side of this little app.
|
||||
> <figure>[](http://danialk.github.io/blog/2013/06/16/reactjs-and-socket-dot-io-chat-application/)</figure>
|
||||
>
|
||||
> [Read the full post...](http://danialk.github.io/blog/2013/06/16/reactjs-and-socket-dot-io-chat-application/)
|
||||
|
||||
## React and Other Frameworks
|
||||
|
||||
[Pete Hunt](http://www.petehunt.net/blog/) wrote an answer on Quora comparing React and Angular directives. At the end, he explains how you can make an Angular directive that is in fact being rendered with React.
|
||||
|
||||
> To set the record straight: React components are far more powerful than Angular templates; they should be compared with Angular's directives instead. So I took the first Google hit for "AngularJS directive tutorial" (AngularJS Directives Tutorial - Fundoo Solutions), rewrote it in React and compared them. [...]
|
||||
>
|
||||
> We've designed React from the beginning to work well with other libraries. Angular is no exception. Let's take the original Angular example and use React to implement the fundoo-rating directive.
|
||||
>
|
||||
> [Read the full post...](http://www.quora.com/Pete-Hunt/Posts/Facebooks-React-vs-AngularJS-A-Closer-Look)
|
||||
|
||||
In the same vein, [Markov Twain](https://twitter.com/markov_twain/status/345702941845499906) re-implemented the examples on the front-page [with Ember](http://jsbin.com/azihiw/2/edit) and [Vlad Yazhbin](https://twitter.com/vla) re-implemented the tutorial [with Angular](http://jsfiddle.net/vla/Cdrse/).
|
||||
|
||||
## Web Components: React & x-tags
|
||||
|
||||
Mozilla and Google are actively working on Web Components. [Vjeux](http://blog.vjeux.com/) wrote a proof of concept that shows how to implement them using React.
|
||||
|
||||
> Using [x-tags](http://www.x-tags.org/) from Mozilla, we can write custom tags within the DOM. This is a great opportunity to be able to write reusable components without being tied to a particular library. I wrote [x-react](https://github.com/vjeux/react-xtags/) to have them being rendered in React.
|
||||
> <figure>[](http://blog.vjeux.com/2013/javascript/custom-components-react-x-tags.html)</figure>
|
||||
>
|
||||
> [Read the full post...](http://blog.vjeux.com/2013/javascript/custom-components-react-x-tags.html)
|
||||
|
||||
## React TodoMVC Example
|
||||
|
||||
[TodoMVC.com](http://todomvc.com/) is a website that collects various implementations of the same basic Todo app. [Pete Hunt](http://www.petehunt.net/blog/) wrote an idiomatic React version.
|
||||
|
||||
> Developers these days are spoiled with choice when it comes to selecting an MV* framework for structuring and organizing their JavaScript web apps.
|
||||
>
|
||||
> To help solve this problem, we created TodoMVC - a project which offers the same Todo application implemented using MV* concepts in most of the popular JavaScript MV* frameworks of today.
|
||||
> <figure>[](http://todomvc.com/labs/architecture-examples/react/)</figure>
|
||||
>
|
||||
> [Read the source code...](https://github.com/tastejs/todomvc/tree/gh-pages/labs/architecture-examples/react)
|
||||
|
||||
## JSX is not HTML
|
||||
|
||||
Many of you pointed out differences between JSX and HTML. In order to clear up some confusion, we have added some documentation that covers the four main differences:
|
||||
|
||||
- [Whitespace removal](http://facebook.github.io/react/docs/jsx-is-not-html.html)
|
||||
- [HTML Entities](http://facebook.github.io/react/docs/jsx-is-not-html.html)
|
||||
- [Comments](http://facebook.github.io/react/docs/jsx-is-not-html.html)
|
||||
- [Custom HTML Attributes](http://facebook.github.io/react/docs/jsx-is-not-html.html)
|
||||
24
docs/_posts/2013-06-21-react-v0-3-3.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "React v0.3.3"
|
||||
layout: post
|
||||
author: Paul O'Shannessy
|
||||
---
|
||||
|
||||
We have a ton of great stuff coming in v0.4, but in the meantime we're releasing v0.3.3. This release addresses some small issues people were having and simplifies our tools to make them easier to use.
|
||||
|
||||
|
||||
## react-tools
|
||||
|
||||
* 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.
|
||||
|
||||
|
||||
## React
|
||||
|
||||
* Allow reusing the same DOM node to render different components. e.g. `React.renderComponent(<div/>, domNode); React.renderComponent(<span/>, domNode);` will work now.
|
||||
|
||||
|
||||
## JSXTransformer
|
||||
|
||||
* Improved the in-browser transformer so that transformed scripts will execute in the expected scope. The allows components to be defined and used from separate files.
|
||||
91
docs/_posts/2013-06-27-community-roundup-3.md
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
title: "Community Round-up #3"
|
||||
layout: post
|
||||
author: Vjeux
|
||||
---
|
||||
|
||||
The highlight of this week is that an interaction-heavy app has been ported to React. React components are solving issues they had with nested views.
|
||||
|
||||
## Moving From Backbone To React
|
||||
|
||||
[Clay Allsopp](http://twitter.com/clayallsopp) successfully ported [Propeller](http://usepropeller.com/blog/posts/from-backbone-to-react/), a fairly big, interaction-heavy JavaScript app, to React.
|
||||
|
||||
> [<img style="float: right; margin: 0 0 10px 10px;" src="/react/img/blog/propeller-logo.png" />](http://usepropeller.com/blog/posts/from-backbone-to-react/)Subviews involve a lot of easy-to-forget boilerplate that Backbone (by design) doesn't automate. Libraries like Backbone.Marionette offer more abstractions to make view nesting easier, but they're all limited by the fact that Backbone delegates how and went view-document attachment occurs to the application code.
|
||||
>
|
||||
> React, on the other hand, manages the DOM and only exposes real nodes at select points in its API. The "elements" you code in React are actually objects which wrap DOM nodes, not the actual objects which get inserted into the DOM. Internally, React converts those abstractions into actual DOMElements and fills out the document accordingly. [...]
|
||||
>
|
||||
> We moved about 20 different Backbone view classes to React over the past few weeks, including the live-preview pane that you see in our little iOS demo. Most importantly, it's allowed us to put energy into making each component work great on its own, instead of spending extra cycles to ensure they function in unison. For that reason, we think React is a more scalable way to build view-intensive apps than Backbone alone, and it doesn't require you to drop-everything-and-refactor like a move to Ember or Angular would demand.
|
||||
>
|
||||
> [Read the full post...](http://usepropeller.com/blog/posts/from-backbone-to-react/)
|
||||
|
||||
## Grunt Task for JSX
|
||||
|
||||
[Eric Clemmons](http://ericclemmons.github.io/) wrote a task for [Grunt](http://gruntjs.com/) that applies the JSX transformation to your Javascript files. It also works with [Browserify](http://browserify.org/) if you want all your files to be concatenated and minified together.
|
||||
|
||||
> Grunt task for compiling Facebook React's .jsx templates into .js
|
||||
>
|
||||
> ```javascript
|
||||
grunt.initConfig({
|
||||
react: {
|
||||
app: {
|
||||
options: { extension: 'js' },
|
||||
files: { 'path/to/output/dir': 'path/to/jsx/templates/dir' }
|
||||
```
|
||||
>
|
||||
> It also works great with `grunt-browserify`!
|
||||
>
|
||||
> ```javascript
|
||||
browserify: {
|
||||
options: {
|
||||
transform: [ require('grunt-react').browserify ]
|
||||
},
|
||||
app: {
|
||||
src: 'path/to/source/main.js',
|
||||
dest: 'path/to/target/output.js'
|
||||
```
|
||||
>
|
||||
> [Check out the project ...](https://github.com/ericclemmons/grunt-react)
|
||||
|
||||
## Backbone/Handlebars Nested Views
|
||||
|
||||
[Joel Burget](http://joelburget.com/) wrote a blog post talking about the way we would write React-like components in Backbone and Handlebars.
|
||||
|
||||
> The problem here is that we're trying to maniplate a tree, but there's a textual layer we have to go through. Our views are represented as a tree - the subviews are children of CommentCollectionView - and they end up as part of a tree in the DOM. But there's a Handlebars layer in the middle (which deals in flat strings), so the hierarchy must be destructed and rebuilt when we render.
|
||||
>
|
||||
> What does it take to render a collection view? In the Backbone/Handlebars view of the world you have to render the template (with stubs), render each subview which replaces a stub, and keep a reference to each subview (or anything within the view that could change in the future).
|
||||
>
|
||||
> So while our view is conceptually hierarchical, due to the fact that it has to go through a flat textual representation, we need to do a lot of extra work to reassemble that structure after rendering.
|
||||
>
|
||||
> [Read the full post...](http://joelburget.com/react/)
|
||||
|
||||
## JSRomandie Meetup
|
||||
|
||||
[Renault John Lecoultre](https://twitter.com/renajohn/) from [BugBuster](http://www.bugbuster.com) did a React introduction talk at a JS meetup called [JS Romandie](https://twitter.com/jsromandie) last week.
|
||||
|
||||
<script async class="speakerdeck-embed" data-id="888a9d50c01b01300df36658d0894ac1" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
|
||||
|
||||
## CoffeeScript integration
|
||||
|
||||
[Vjeux](http://blog.vjeux.com/) used the fact that JSX is just a syntactic sugar on-top of regular JS to rewrite the React front-page examples in CoffeeScript.
|
||||
|
||||
> Multiple people asked what's the story about JSX and CoffeeScript. There is no JSX pre-processor for CoffeeScript and I'm not aware of anyone working on it. Fortunately, CoffeeScript is pretty expressive and we can play around the syntax to come up with something that is usable.
|
||||
>
|
||||
> ```javascript
|
||||
{div, h3, textarea} = React.DOM
|
||||
(div {className: 'MarkdownEditor'}, [
|
||||
(h3 {}, 'Input'),
|
||||
(textarea {onKeyUp: @handleKeyUp, ref: 'textarea'},
|
||||
@state.value
|
||||
)
|
||||
])
|
||||
```
|
||||
>
|
||||
> [Read the full post...](http://blog.vjeux.com/2013/javascript/react-coffeescript.html)
|
||||
|
||||
## Tutorial in Plain Javascript
|
||||
|
||||
We've seen a lot of people comparing React with various frameworks. [Ricardo Tomasi](http://ricardo.cc/) decided to re-implement the tutorial without any framework, just plain Javascript.
|
||||
|
||||
> Facebook & Instagram launched the React framework and an accompanying tutorial. Developer Vlad Yazhbin decided to rewrite that using AngularJS. The end result is pretty neat, but if you're like me you will not actually appreciate the HTML speaking for itself and doing all the hard work. So let's see what that looks like in plain javascript.
|
||||
>
|
||||
> [Read the full post...](http://ricardo.cc/2013/06/07/react-tutorial-rewritten-in-plain-javascript.html)
|
||||
52
docs/_posts/2013-07-02-react-v0-4-autobind-by-default.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "New in React v0.4: Autobind by Default"
|
||||
layout: post
|
||||
author: Paul O'Shannessy
|
||||
---
|
||||
|
||||
React v0.4 is very close to completion. As we finish it off, we'd like to share with you some of the major changes we've made since v0.3. This is the first of several posts we'll be making over the next week.
|
||||
|
||||
|
||||
## What is React.autoBind?
|
||||
|
||||
If you take a look at most of our current examples, you'll see us using `React.autoBind` for event handlers. This is used in place of `Function.prototype.bind`. Remember that in JS, [function calls are late-bound](http://bonsaiden.github.io/JavaScript-Garden/#function.this). That means that if you simply pass a function around, the `this` used inside won't necessarily be the `this` you expect. `Function.prototype.bind` creates a new, properly bound, function so that when called, `this` is exactly what you expect it to be.
|
||||
|
||||
Before we launched React, we would write this:
|
||||
|
||||
```js{4}
|
||||
React.createClass({
|
||||
onClick: function(event) {/* do something with this */},
|
||||
render: function() {
|
||||
return <button onClick={this.onClick.bind(this)} />;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
We wrote `React.autoBind` as a way to cache the function creation and save on memory usage. Since `render` can get called multiple times, if you used `this.onClick.bind(this)` you would actually create a new function on each pass. With React v0.3 you were able to write this instead:
|
||||
|
||||
```js{2,4}
|
||||
React.createClass({
|
||||
onClick: React.autoBind(function(event) {/* do something with this */}),
|
||||
render: function() {
|
||||
return <button onClick={this.onClick} />;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## What's Changing in v0.4?
|
||||
|
||||
After using `React.autoBind` for a few weeks, we realized that there were very few times that we didn't want that behavior. So we made it the default! Now all methods defined within `React.createClass` will already be bound to the correct instance.
|
||||
|
||||
Starting with v0.4 you can just write this:
|
||||
|
||||
```js{2,4}
|
||||
React.createClass({
|
||||
onClick: function(event) {/* do something with this */},
|
||||
render: function() {
|
||||
return <button onClick={this.onClick} />;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
For v0.4 we will simply be making `React.autoBind` a no-op — it will just return the function you pass to it. Most likely you won't have to change your code to account for this change, though we encourage you to update. We'll publish a migration guide documenting this and other changes that come along with React v0.4.
|
||||
58
docs/_posts/2013-07-03-community-roundup-4.md
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: "Community Round-up #4"
|
||||
layout: post
|
||||
author: Vjeux
|
||||
---
|
||||
|
||||
React reconciliation process appears to be very well suited to implement a text editor with a live preview as people at Khan Academy show us.
|
||||
|
||||
## Khan Academy
|
||||
|
||||
[Ben Kamens](http://bjk5.com/) explains how [Ben Alpert](http://benalpert.com/) and [Joel Burget](http://joelburget.com/) are promoting React inside of [Khan Academy](https://www.khanacademy.org/). They now have three projects in the works using React.
|
||||
|
||||
> Recently two Khan Academy devs dropped into our team chat and said they were gonna use React to write a new feature. They even hinted that we may want to adopt it product-wide.
|
||||
>
|
||||
> "The library is only a week old. It's a brand new way of thinking about things. We're the first to use it outside of Facebook. Heck, even the React devs were surprised to hear we're using this in production!!!"
|
||||
>
|
||||
> [Read the full post...](http://bjk5.com/post/53742233351/getting-your-team-to-adopt-new-technology)
|
||||
|
||||
The best part is the demo of how React reconciliation process makes live editing more user-friendly.
|
||||
|
||||
> Our renderer, post-React, is on the left. A typical math editor's preview is on the right.
|
||||
> <figure>[<img src="/react/img/blog/monkeys.gif" width="70%" />](http://bjk5.com/post/53742233351/getting-your-team-to-adopt-new-technology)</figure>
|
||||
|
||||
## React Snippets
|
||||
|
||||
Over the past several weeks, members of our team, [Pete Hunt](http://www.petehunt.net/) and [Paul O'Shannessy](http://zpao.com/), answered many questions that were asked in the [React group](https://groups.google.com/forum/#!forum/reactjs). They give a good overview of how to integrate React with other libraries and APIs through the use of [Mixins](/react/docs/reusable-components.html) and [Lifecycle Methods](/react/docs/working-with-the-browser.html).
|
||||
|
||||
> [Listening Scroll Event](https://groups.google.com/forum/#!topic/reactjs/l6PnP8qbofk)
|
||||
>
|
||||
> * [JSFiddle](http://jsfiddle.net/aabeL/1/): Basically I've given you two mixins. The first lets you react to global scroll events. The second is, IMO, much more useful: it gives you scroll start and scroll end events, which you can use with setState() to create components that react based on whether the user is scrolling or not.
|
||||
>
|
||||
> [Fade-in Transition](https://groups.google.com/forum/#!topic/reactjs/RVAY_eQmdpo)
|
||||
>
|
||||
> * [JSFiddle](http://jsfiddle.net/ufe8k/1/): Creating a new `<FadeInWhenAdded>` component and using jQuery `.fadeIn()` function on the DOM node.
|
||||
> * [JSFiddle](http://jsfiddle.net/R8f5L/5/): Using CSS transition instead.
|
||||
>
|
||||
> [Socket.IO Integration](https://groups.google.com/forum/#!topic/reactjs/pyUZBRWcHB4)
|
||||
>
|
||||
> * [Gist](https://gist.github.com/zpao/5686416): The big thing to notice is that my component is pretty dumb (it doesn't have to be but that's how I chose to model it). All it does is render itself based on the props that are passed in. renderOrUpdate is where the "magic" happens.
|
||||
> * [Gist](https://gist.github.com/petehunt/5687230): This example is doing everything -- including the IO -- inside of a single React component.
|
||||
> * [Gist](https://gist.github.com/petehunt/5687276): One pattern that we use at Instagram a lot is to employ separation of concerns and consolidate I/O and state into components higher in the hierarchy to keep the rest of the components mostly stateless and purely display.
|
||||
>
|
||||
> [Sortable jQuery Plugin Integration](https://groups.google.com/forum/#!topic/reactjs/mHfBGI3Qwz4)
|
||||
>
|
||||
> * [JSFiddle](http://jsfiddle.net/LQxy7/): Your React component simply render empty divs, and then in componentDidMount() you call React.renderComponent() on each of those divs to set up a new root React tree. Be sure to explicitly unmountAndReleaseReactRootNode() for each component in componentWillUnmount().
|
||||
|
||||
## Introduction to React Screencast
|
||||
|
||||
[Pete Hunt](http://www.petehunt.net/) recorded himself implementing a simple `<Blink>` tag in React.
|
||||
|
||||
<figure><iframe src="http://player.vimeo.com/video/67248575" width="500" height="340" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></figure>
|
||||
|
||||
## Snake in React
|
||||
|
||||
[Tom Occhino](http://tomocchino.com/) implemented Snake in 150 lines with React.
|
||||
|
||||
> [Check the source on Github](https://github.com/tomocchino/react-snake/blob/master/src/snake.js)
|
||||
> <figure>[](http://tomocchino.github.io/react-snake/)</figure>
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: "New in React v0.4: Prop Validation and Default Values"
|
||||
layout: post
|
||||
author: Paul O'Shannessy
|
||||
---
|
||||
|
||||
Many of the questions we got following the public launch of React revolved around `props`, specifically that people wanted to do validation and to make sure their components had sensible defaults.
|
||||
|
||||
|
||||
## Validation
|
||||
|
||||
Oftentimes you want to validate your `props` before you use them. Perhaps you want to ensure they are a specific type. Or maybe you want to restrict your prop to specific values. Or maybe you want to make a specific prop required. This was always possible — you could have written validations in your `render` or `componentWillReceiveProps` functions, but that gets clunky fast.
|
||||
|
||||
React v0.4 will provide a nice easy way for you to use built-in validators, or to even write your own.
|
||||
|
||||
```js
|
||||
React.createClass({
|
||||
propTypes: {
|
||||
// An optional string prop named "description".
|
||||
description: React.PropTypes.string,
|
||||
|
||||
// A required enum prop named "category".
|
||||
category: React.PropTypes.oneOf(['News','Photos']).isRequired,
|
||||
|
||||
// A prop named "dialog" that requires an instance of Dialog.
|
||||
dialog: React.PropTypes.instanceOf(Dialog).isRequired
|
||||
},
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Default Values
|
||||
|
||||
One common pattern we've seen with our React code is to do something like this:
|
||||
|
||||
```js
|
||||
React.createClass({
|
||||
render: function() {
|
||||
var value = this.props.value || 'default value';
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Do this for a few `props` across a few components and now you have a lot of redundant code. Starting with React v0.4, you can provide default values in a declarative way:
|
||||
|
||||
```js
|
||||
React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
value: 'default value'
|
||||
};
|
||||
}
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
We will use the cached result of this function before each `render`. We also perform all validations before each `render` to ensure that you have all of the data you need in the right form before you try to use it.
|
||||
|
||||
- - -
|
||||
|
||||
Both of these features are entirely optional. We've found them to be increasingly valuable at Facebook as our applications grow and evolve, and we hope others find them useful as well.
|
||||
40
docs/_posts/2013-07-17-react-v0-4-0.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "React v0.4.0"
|
||||
layout: post
|
||||
author: Paul O'Shannessy
|
||||
---
|
||||
|
||||
Over the past 2 months we've been taking feedback and working hard to make React even better. We fixed some bugs, made some under-the-hood improvements, and added several features that we think will improve the experience developing with React. Today we're proud to announce the availability of React v0.4!
|
||||
|
||||
|
||||
This release could not have happened without the support of our growing community. Since launch day, the community has contributed blog posts, questions to the [Google Group](http://groups.google.com/group/reactjs), and issues and pull requests on GitHub. We've had contributions ranging from documentation improvements to major changes to React's rendering. We've seen people integrate React into the tools they're using and the products they're building, and we're all very excited to see what our budding community builds next!
|
||||
|
||||
React v0.4 has some big changes. We've also restructured the documentation to better communicate how to use React. We've summarized the changes below and linked to documentation where we think it will be especially useful.
|
||||
|
||||
When you're ready, [go download it](/react/downloads.html)!
|
||||
|
||||
|
||||
### React
|
||||
|
||||
* Switch from using `id` attribute to `data-reactid` to track DOM nodes. This allows you to integrate with other JS and CSS libraries more easily.
|
||||
* Support for more DOM elements and attributes (e.g., `<canvas>`)
|
||||
* Improved server-side rendering APIs. `React.renderComponentToString(<component>, callback)` allows you to use React on the server and generate markup which can be sent down to the browser.
|
||||
* `prop` improvements: validation and default values. [Read our blog post for details...](http://facebook.github.io/react/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.html)
|
||||
* Support for the `key` prop, which allows for finer control over reconciliation. [Read the docs for details...](http://facebook.github.io/react/docs/multiple-components.html)
|
||||
* Removed `React.autoBind`. [Read our blog post for details...](http://facebook.github.io/react/blog/2013/07/02/react-v0-4-autobind-by-default.html)
|
||||
* Improvements to forms. We've written wrappers around `<input>`, `<textarea>`, `<option>`, and `<select>` in order to standardize many inconsistencies in browser implementations. This includes support for `defaultValue`, and improved implementation of the `onChange` event, and circuit completion. [Read the docs for details...](http://facebook.github.io/react/docs/forms.html)
|
||||
* We've implemented an improved synthetic event system that conforms to the W3C spec.
|
||||
* Updates to your component are batched now, which may result in a significantly faster re-render of components. `this.setState` now takes an optional callback as its second parameter. If you were using `onClick={this.setState.bind(this, state)}` previously, you'll want to make sure you add a third parameter so that the event is not treated as the callback.
|
||||
|
||||
### JSX
|
||||
|
||||
* Support for comment nodes `<div>{/* this is a comment and won't be rendered */}</div>`
|
||||
* Children are now transformed directly into arguments instead of being wrapped in an array
|
||||
E.g. `<div><Component1/><Component2/></div>` is transformed into `React.DOM.div(null, Component1(null), Component2(null))`.
|
||||
Previously this would be transformed into `React.DOM.div(null, [Component1(null), Component2(null)])`.
|
||||
If you were using React without JSX previously, your code should still work.
|
||||
|
||||
### react-tools
|
||||
|
||||
* Fixed a number of bugs when transforming directories
|
||||
* No longer re-write `require()`s to be relative unless specified
|
||||
99
docs/_posts/2013-07-23-community-roundup-5.md
Normal file
@@ -0,0 +1,99 @@
|
||||
---
|
||||
title: "Community Round-up #5"
|
||||
layout: post
|
||||
author: Vjeux
|
||||
---
|
||||
|
||||
We launched the [React Facebook Page](https://www.facebook.com/react) along with the React v0.4 launch. 700 people already liked it to get updated on the project :)
|
||||
|
||||
## Cross-browser onChange
|
||||
|
||||
[Ben Alpert](http://benalpert.com/) from [Khan Academy](https://www.khanacademy.org/) worked on a cross-browser implementation of `onChange` event that landed in v0.4. He wrote a blog post explaining the various browser quirks he had to deal with.
|
||||
|
||||
> First off, what is the input event? If you have an `<input>` element and want to receive events whenever the value changes, the most obvious thing to do is to listen to the change event. Unfortunately, change fires only after the text field is defocused, rather than on each keystroke. The next obvious choice is the keyup event, which is triggered whenever a key is released. Unfortunately, keyup doesn't catch input that doesn't involve the keyboard (e.g., pasting from the clipboard using the mouse) and only fires once if a key is held down, rather than once per inserted character.
|
||||
>
|
||||
> Both keydown and keypress do fire repeatedly when a key is held down, but both fire immediately before the value changes, so to read the new value you have to defer the handler to the next event loop using `setTimeout(fn, 0)` or similar, which slows down your app. Of course, like keyup, neither keydown nor keypress fires for non-keyboard input events, and all three can fire in cases where the value doesn't change at all (such as when pressing the arrow keys).
|
||||
>
|
||||
> [Read the full post...](http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html)
|
||||
|
||||
|
||||
## React Samples
|
||||
|
||||
Learning a new library is always easier when you have working examples you can play with. [jwh](https://github.com/jhw) put many of them on his [react-samples Github repo](https://github.com/jhw/react-samples).
|
||||
|
||||
> Some simple examples with Facebook's React framework
|
||||
>
|
||||
> * Bootstrap action bar, modal and table [#1](https://rawgithub.com/jhw/react-samples/master/html/actionbar.html),
|
||||
> [#2](https://rawgithub.com/jhw/react-samples/master/html/bootstrap_actionbar.html),
|
||||
> [#3](https://rawgithub.com/jhw/react-samples/master/html/bootstrap_modal.html),
|
||||
> [#4](https://rawgithub.com/jhw/react-samples/master/html/bootstrap_striped_table.html)
|
||||
> * Comments [#1](https://rawgithub.com/jhw/react-samples/master/html/comments1.html),
|
||||
> [#2](https://rawgithub.com/jhw/react-samples/master/html/comments2.html)
|
||||
> * Data Table [#1](https://rawgithub.com/jhw/react-samples/master/html/datatable.html),
|
||||
> [#2](https://rawgithub.com/jhw/react-samples/master/html/datatable2.html),
|
||||
> [#3](https://rawgithub.com/jhw/react-samples/master/html/datatable3.html),
|
||||
> [#4](https://rawgithub.com/jhw/react-samples/master/html/datatable4.html),
|
||||
> [#5](https://rawgithub.com/jhw/react-samples/master/html/datatable5.html)
|
||||
> * Filter Bar [#1](https://rawgithub.com/jhw/react-samples/master/html/filterbar.html),
|
||||
> [#2](https://rawgithub.com/jhw/react-samples/master/html/filterbar2.html),
|
||||
> [#3](https://rawgithub.com/jhw/react-samples/master/html/filterbar3.html),
|
||||
> [#4](https://rawgithub.com/jhw/react-samples/master/html/filterbar4.html),
|
||||
> [#5](https://rawgithub.com/jhw/react-samples/master/html/filterbar5.html)
|
||||
> * Fundoo Rating [#1](https://rawgithub.com/jhw/react-samples/master/html/fundoo.html)
|
||||
> * Line Char: [#1](https://rawgithub.com/jhw/react-samples/master/html/linechart.html),
|
||||
> [#2](https://rawgithub.com/jhw/react-samples/master/html/linechart2.html)
|
||||
> * Multi tabs [#1](https://rawgithub.com/jhw/react-samples/master/html/multitabs.html)
|
||||
> * Select [#1](https://rawgithub.com/jhw/react-samples/master/html/select.html)
|
||||
> * Simple Tabs [#1](https://rawgithub.com/jhw/react-samples/master/html/simpletabs.html),
|
||||
> [#2](https://rawgithub.com/jhw/react-samples/master/html/simpletabs2.html),
|
||||
> [#3](https://rawgithub.com/jhw/react-samples/master/html/simpletabs3.html),
|
||||
> [#4](https://rawgithub.com/jhw/react-samples/master/html/simpletabs4.html)
|
||||
> * Toggle [#1](https://rawgithub.com/jhw/react-samples/master/html/toggle.html)
|
||||
|
||||
|
||||
## React Chosen Wrapper
|
||||
|
||||
[Cheng Lou](https://github.com/chenglou) wrote a wrapper for the [Chosen](http://harvesthq.github.io/chosen/) input library called [react-chosen](https://github.com/chenglou/react-chosen). It took just 25 lines to be able to use jQuery component as a React one.
|
||||
|
||||
```javascript
|
||||
React.renderComponent(
|
||||
<Chosen noResultsText="No result" value="Harvest" onChange={doSomething}>
|
||||
<option value="Facebook">Facebook</option>
|
||||
<option value="Harvest">Harvest</option>
|
||||
</Chosen>
|
||||
, document.body);
|
||||
```
|
||||
|
||||
|
||||
## JSX and ES6 Template Strings
|
||||
|
||||
[Domenic Denicola](http://domenicdenicola.com/) wrote a slide deck about the great applications of ES6 features and one slide shows how we could use Template Strings to compile JSX at run-time without the need for a pre-processing phase.
|
||||
|
||||
<figure><iframe src="http://www.slideshare.net/slideshow/embed_code/24187146?rel=0&startSlide=36" width="600" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen webkitallowfullscreen mozallowfullscreen> </iframe></figure>
|
||||
|
||||
|
||||
## React Presentation
|
||||
|
||||
[Tom Occhino](http://tomocchino.com/) and [Jordan Walke](https://github.com/jordwalke), React developers, did a presentation of React at Facebook Seattle's office. Check out the first 25 minutes for the presentation and the remaining 45 for a Q&A. I highly recommend you watching this video.
|
||||
|
||||
<figure><iframe width="650" height="400" src="//www.youtube.com/embed/XxVg_s8xAms" frameborder="0" allowfullscreen></iframe></figure>
|
||||
|
||||
|
||||
## Docs
|
||||
|
||||
[Pete Hunt](http://www.petehunt.net/) rewrote the entirety of the docs for v0.4. The goal was to add more explanation about why we built React and what the best practices are.
|
||||
|
||||
> Guides
|
||||
>
|
||||
> * [Why React?](/react/docs/why-react.html)
|
||||
> * [Displaying Data](/react/docs/displaying-data.html)
|
||||
> * [JSX in Depth](/react/docs/jsx-in-depth.html)
|
||||
> * [JSX Gotchas](/react/docs/jsx-gotchas.html)
|
||||
> * [Interactivity and Dynamic UIs](/react/docs/interactivity-and-dynamic-uis.html)
|
||||
> * [Multiple Components](/react/docs/multiple-components.html)
|
||||
> * [Reusable Components](/react/docs/reusable-components.html)
|
||||
> * [Forms](/react/docs/forms.html)
|
||||
> * [Working With the Browser](/react/docs/working-with-the-browser.html)
|
||||
> * [More About Refs](/react/docs/more-about-refs.html)
|
||||
> * [Tooling integration](/react/docs/tooling-integration.html)
|
||||
> * [Reference](/react/docs/top-level-api.html)
|
||||
25
docs/_posts/2013-07-26-react-v0-4-1.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: "React v0.4.1"
|
||||
layout: post
|
||||
author: Paul O'Shannessy
|
||||
---
|
||||
|
||||
React v0.4.1 is a small update, mostly containing correctness fixes. Some code has been restructured internally but those changes do not impact any of our public APIs.
|
||||
|
||||
|
||||
## React
|
||||
|
||||
* `setState` callbacks are now executed in the scope of your component.
|
||||
* `click` events now work on Mobile Safari.
|
||||
* Prevent a potential error in event handling if `Object.prototype` is extended.
|
||||
* Don't set DOM attributes to the string `"undefined"` on update when previously defined.
|
||||
* Improved support for `<iframe>` attributes.
|
||||
* Added checksums to detect and correct cases where server-side rendering markup mismatches what React expects client-side.
|
||||
|
||||
|
||||
## JSXTransformer
|
||||
|
||||
* Improved environment detection so it can be run in a non-browser environment.
|
||||
|
||||
|
||||
[Download it now!](/react/downloads.html)
|
||||
54
docs/_posts/2013-07-30-use-react-and-jsx-in-ruby-on-rails.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "Use React and JSX in Ruby on Rails"
|
||||
layout: post
|
||||
author: Paul O'Shannessy
|
||||
---
|
||||
|
||||
Today we're releasing a gem to make it easier to use React and JSX in Ruby on Rails applications: [react-rails](https://github.com/facebook/react-rails).
|
||||
|
||||
|
||||
This gem has 2 primary purposes:
|
||||
|
||||
1. To package `react.js` in a way that's easy to use and easy to update.
|
||||
2. To allow you to write JSX without an external build step to transform that into JS.
|
||||
|
||||
|
||||
## Packaging react.js
|
||||
|
||||
To make `react.js` available for use client-side, simply add `react` to your manifest, and declare the variant you'd like to use in your environment. When you use `:production`, the minified and optimized `react.min.js` will be used instead of the development version. For example:
|
||||
|
||||
```ruby
|
||||
# config/environments/development.rb
|
||||
|
||||
MyApp::Application.configure do
|
||||
config.react.variant = :development
|
||||
# use :production in production.rb
|
||||
end
|
||||
```
|
||||
|
||||
```js
|
||||
// app/assets/javascript/application.js
|
||||
|
||||
//= require react
|
||||
```
|
||||
|
||||
|
||||
## Writing JSX
|
||||
|
||||
When you name your file with `myfile.js.jsx`, `react-rails` will automatically try to transform that file. For the time being, we still require that you include the docblock at the beginning of the file. For example, this file will get transformed on request.
|
||||
|
||||
```js
|
||||
/** @jsx React.DOM */
|
||||
React.renderComponent(<MyComponent/>, document.body)
|
||||
```
|
||||
|
||||
|
||||
## Asset Pipeline
|
||||
|
||||
`react-rails` takes advantage of the [asset pipeline](http://guides.rubyonrails.org/asset_pipeline.html) that was introduced in Rails 3.1. A very important part of that pipeline is the `assets:precompile` Rake task. `react-rails` will ensure that your JSX files will be transformed into regular JS before all of your assets are minified and packaged.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Installation follows the same process you're familiar with. You can install it globally with `gem install react-rails`, though we suggest you add the dependency to your `Gemfile` directly.
|
||||
|
||||
80
docs/_posts/2013-08-05-community-roundup-6.md
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: "Community Round-up #6"
|
||||
layout: post
|
||||
author: Vjeux
|
||||
---
|
||||
|
||||
This is the first Community Round-up where none of the items are from Facebook/Instagram employees. It's great to see the adoption of React growing.
|
||||
|
||||
## React Game Tutorial
|
||||
|
||||
[Caleb Cassel](https://twitter.com/CalebCassel) wrote a [step-by-step tutorial](https://rawgithub.com/calebcassel/react-demo/master/part1.html) about making a small game. It covers JSX, State and Events, Embedded Components and Integration with Backbone.
|
||||
<figure>[](https://rawgithub.com/calebcassel/react-demo/master/part1.html)</figure>
|
||||
|
||||
|
||||
## Reactify
|
||||
|
||||
[Andrey Popp](http://andreypopp.com/) created a [Browserify](http://browserify.org/) helper to compile JSX files.
|
||||
|
||||
> Browserify v2 transform for `text/jsx`. Basic usage is:
|
||||
>
|
||||
> ```
|
||||
% browserify -t reactify main.jsx
|
||||
```
|
||||
>
|
||||
> `reactify` transform activates for files with either `.jsx` extension or `/** @jsx React.DOM */` pragma as a first line for any `.js` file.
|
||||
>
|
||||
> [Check it out on Github...](https://github.com/andreypopp/reactify)
|
||||
|
||||
|
||||
|
||||
## React Integration with Este
|
||||
|
||||
[Daniel Steigerwald](http://daniel.steigerwald.cz/) is now using React within [Este](https://github.com/steida/este), which is a development stack for web apps in CoffeeScript that are statically typed using the Closure Library.
|
||||
|
||||
```coffeescript
|
||||
este.demos.react.todoApp = este.react.create (`/** @lends {React.ReactComponent.prototype} */`)
|
||||
render: ->
|
||||
@div [
|
||||
este.demos.react.todoList 'items': @state['items']
|
||||
if @state['items'].length
|
||||
@p "#{@state['items'].length} items."
|
||||
@form 'onSubmit': @onFormSubmit, [
|
||||
@input
|
||||
'onChange': @onChange
|
||||
'value': @state['text']
|
||||
'autoFocus': true
|
||||
'ref': 'textInput'
|
||||
@button "Add ##{@state['items'].length + 1}"
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
[Check it out on Github...](https://github.com/steida/este-library/blob/master/este/demos/thirdparty/react/start.coffee)
|
||||
|
||||
|
||||
## React Stylus Boilerplate
|
||||
|
||||
[Zaim Bakar](http://zaim.github.io/) shared his boilerplate to get started with Stylus CSS processor.
|
||||
|
||||
> This is my boilerplate React project using Grunt as the build tool, and Stylus as my CSS preprocessor.
|
||||
>
|
||||
> - Very minimal HTML boilerplate
|
||||
> - Uses Stylus, with nib included
|
||||
> - Uses two build targets:
|
||||
> - `grunt build` to compile JSX and Stylus into a development build
|
||||
> - `grunt dist` to minify and optimize the development build for production
|
||||
>
|
||||
> [Check it out on Github...](https://github.com/zaim/react-stylus-boilerplate)
|
||||
|
||||
|
||||
## WebFUI
|
||||
|
||||
[Conrad Barski](http://lisperati.com/), author of the popular book [Land of Lisp](http://landoflisp.com/), wants to use React for his ClojureScript library called [WebFUI](https://github.com/drcode/webfui).
|
||||
|
||||
> I'm the author of "[Land of Lisp](http://landoflisp.com/)" and I love your framework. I built a somewhat similar framework a year ago [WebFUI](https://github.com/drcode/webfui) aimed at ClojureScript. My framework also uses global event delegates, a global "render" function, DOM reconciliation, etc just like react.js. (Of course these ideas all have been floating around the ether for ages, always great to see more people building on them.)
|
||||
>
|
||||
> Your implementation is more robust, and so I think the next point release of webfui will simply delegate all the "hard work" to react.js and will only focus on the areas where it adds value (enabling purely functional UI programming in clojurescript, and some other stuff related to streamlining event handling)
|
||||
<figure>[](https://groups.google.com/forum/#!msg/reactjs/e3bYersyd64/qODfcuBR9LwJ)</figure>
|
||||
>
|
||||
> [Read the full post...](https://groups.google.com/forum/#!msg/reactjs/e3bYersyd64/qODfcuBR9LwJ)
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: "Use React and JSX in Python Applications"
|
||||
layout: post
|
||||
author: Kunal Mehta
|
||||
---
|
||||
|
||||
Today we're happy to announce the initial release of [PyReact](https://github.com/facebook/react-python), which makes it easier to use React and JSX in your Python applications. It's designed to provide an API to transform your JSX files into JavaScript, as well as provide access to the latest React source files.
|
||||
|
||||
## Usage
|
||||
|
||||
Transform your JSX files via the provided `jsx` module:
|
||||
|
||||
```python
|
||||
from react import jsx
|
||||
|
||||
# For multiple paths, use the JSXTransformer class.
|
||||
transformer = jsx.JSXTransformer()
|
||||
for jsx_path, js_path in my_paths:
|
||||
transformer.transform(jsx_path, js_path)
|
||||
|
||||
# For a single file, you can use a shortcut method.
|
||||
jsx.transform('path/to/input/file.jsx', 'path/to/output/file.js')
|
||||
```
|
||||
|
||||
For full paths to React files, use the `source` module:
|
||||
|
||||
```python
|
||||
from react import source
|
||||
|
||||
# path_for raises IOError if the file doesn't exist.
|
||||
react_js = source.path_for('react.min.js')
|
||||
```
|
||||
|
||||
## Django
|
||||
|
||||
PyReact includes a JSX compiler for [django-pipeline](https://github.com/cyberdelia/django-pipeline). Add it to your project's pipeline settings like this:
|
||||
|
||||
```python
|
||||
PIPELINE_COMPILERS = (
|
||||
'react.utils.pipeline.JSXCompiler',
|
||||
)
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
PyReact is hosted on PyPI, and can be installed with `pip`:
|
||||
|
||||
$ pip install PyReact
|
||||
|
||||
Alternatively, add it into your `requirements` file:
|
||||
|
||||
PyReact==0.1.1
|
||||
|
||||
**Dependencies**: PyReact uses [PyExecJS](https://github.com/doloopwhile/PyExecJS) to execute the bundled React code, which requires that a JS runtime environment is installed on your machine. We don't explicitly set a dependency on a runtime environment; Mac OS X comes bundled with one. If you're on a different platform, we recommend [PyV8](https://code.google.com/p/pyv8/).
|
||||
|
||||
For the initial release, we've only tested on Python 2.7. Look out for support for Python 3 in the future, and if you see anything that can be improved, we welcome your [contributions](https://github.com/facebook/react-python/blob/master/CONTRIBUTING.md)!
|
||||
74
docs/_posts/2013-08-26-community-roundup-7.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: "Community Round-up #7"
|
||||
layout: post
|
||||
author: Vjeux
|
||||
---
|
||||
|
||||
It's been three months since we open sourced React and it is going well. Some stats so far:
|
||||
|
||||
* 114 285 unique visitors on this website
|
||||
* [1933 stars](https://github.com/facebook/react/stargazers) and [210 forks](https://github.com/facebook/react/network/members)
|
||||
* [226 posts on Google Group](https://groups.google.com/forum/#!forum/reactjs)
|
||||
* [76 Github projects using React](https://gist.github.com/vjeux/6335762)
|
||||
* [30 contributors](https://github.com/facebook/react/graphs/contributors)
|
||||
* [15 blog posts](http://facebook.github.io/react/blog/)
|
||||
* 2 early adopters: [Khan Academy](http://benalpert.com/2013/06/09/using-react-to-speed-up-khan-academy.html) and [Propeller](http://usepropeller.com/blog/posts/from-backbone-to-react/)
|
||||
|
||||
|
||||
## Wolfenstein Rendering Engine Ported to React
|
||||
|
||||
[Pete Hunt](http://www.petehunt.net/) ported the render code of the web version of Wolfenstein 3D to React. Check out [the demo](http://www.petehunt.net/wolfenstein3D-react/wolf3d.html) and [render.js](https://github.com/petehunt/wolfenstein3D-react/blob/master/js/renderer.js#L183) file for the implementation.
|
||||
<figure>[](http://www.petehunt.net/wolfenstein3D-react/wolf3d.html)</figure>
|
||||
|
||||
|
||||
## React & Meteor
|
||||
|
||||
[Ben Newman](https://twitter.com/benjamn) made a [13-lines wrapper](https://github.com/benjamn/meteor-react/blob/master/lib/mixin.js) to use React and Meteor together. [Meteor](http://www.meteor.com/) handles the real-time data synchronization between client and server. React provides the declarative way to write the interface and only updates the parts of the UI that changed.
|
||||
|
||||
> This repository defines a Meteor package that automatically integrates the React rendering framework on both the client and the server, to complement or replace the default Handlebars templating system.
|
||||
>
|
||||
> The React core is officially agnostic about how you fetch and update your data, so it is far from obvious which approach is the best. This package provides one answer to that question (use Meteor!), and I hope you will find it a compelling combination.
|
||||
>
|
||||
>```javascript
|
||||
>var MyComponent = React.createClass({
|
||||
> mixins: [MeteorMixin],
|
||||
>
|
||||
> getMeteorState: function() {
|
||||
> return { foo: Session.get('foo') };
|
||||
> },
|
||||
>
|
||||
> render: function() {
|
||||
> return <div>{this.state.foo}</div>;
|
||||
> }
|
||||
>});
|
||||
>```
|
||||
>
|
||||
> Dependencies will be registered for any data accesses performed by getMeteorState so that the component can be automatically re-rendered whenever the data changes.
|
||||
>
|
||||
> [Read more ...](https://github.com/benjamn/meteor-react)
|
||||
|
||||
## React Page
|
||||
|
||||
[Jordan Walke](https://github.com/jordwalke) implemented a complete React project creator called [react-page](https://github.com/facebook/react-page/). It supports both server-side and client-side rendering, source transform and packaging JSX files using CommonJS modules, and instant reload.
|
||||
|
||||
> Easy Application Development with React JavaScript
|
||||
> <figure>[](https://github.com/facebook/react-page/)</figure>
|
||||
>
|
||||
> **Why Server Rendering?**
|
||||
>
|
||||
> * Faster initial page speed:
|
||||
> * Markup displayed before downloading large JavaScript.
|
||||
> * Markup can be generated more quickly on a fast server than low power client devices.
|
||||
> * Faster Development and Prototyping:
|
||||
> * Instantly refresh your app without waiting for any watch scripts or bundlers.
|
||||
> * Easy deployment of static content pages/blogs: just archive using recursive wget.
|
||||
> * SEO benefits of indexability and perf.
|
||||
>
|
||||
> **How Does Server Rendering Work?**
|
||||
>
|
||||
> * `react-page` computes page markup on the server, sends it to the client so the user can see it quickly.
|
||||
> * The corresponding JavaScript is then packaged and sent.
|
||||
> * The browser runs that JavaScript, so that all of the event handlers, interactions and update code will run seamlessly on top of the server generated markup.
|
||||
> * From the developer's (and the user's) perspective, it's just as if the rendering occurred on the client, only faster.
|
||||
>
|
||||
> [Try it out ...](https://github.com/facebook/react-page/)
|
||||
70
docs/_posts/2013-09-24-community-roundup-8.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: "Community Round-up #8"
|
||||
layout: post
|
||||
author: Vjeux
|
||||
---
|
||||
|
||||
A lot has happened in the month since our last update. Here are some of the more interesting things we've found. But first, we have a couple updates before we share links.
|
||||
|
||||
First, we are organizing a [React Hackathon](http://reactjshack-a-thon.splashthat.com/) in Facebook's Seattle office on Saturday September 28. If you want to hack on React, meet some of the team or win some prizes, feel free to join us!
|
||||
|
||||
We've also reached a point where there are too many questions for us to handle directly. We're encouraging people to ask questions on [StackOverflow](http://stackoverflow.com/questions/tagged/reactjs) using the tag [[reactjs]](http://stackoverflow.com/questions/tagged/reactjs). Many members of the team and community have subscribed to the tag, so feel free to ask questions there. We think these will be more discoverable than Google Groups archives or IRC logs.
|
||||
|
||||
## Javascript Jabber
|
||||
|
||||
[Pete Hunt](http://www.petehunt.net/) and [Jordan Walke](https://github.com/jordwalke) were interviewed on [Javascript Jabber](http://javascriptjabber.com/073-jsj-react-with-pete-hunt-and-jordan-walke/) for an hour. They go over many aspects of React such as 60 FPS, Data binding, Performance, Diffing Algorithm, DOM Manipulation, Node.js support, server-side rendering, JSX, requestAnimationFrame and the community. This is a gold mine of information about React.
|
||||
|
||||
> **PETE:** So React was designed all around that. Conceptually, how you build a React app is that every time your data changes, it's like hitting the refresh button in a server-rendered app. What we do is we conceptually throw out all of the markup and event handlers that you've registered and we reset the whole page and then we redraw the entire page. If you're writing a server-rendered app, handling updates is really easy because you hit the refresh button and you're pretty much guaranteed to get what you expect.
|
||||
>
|
||||
> **MERRICK:** That's true. You don't get into these odd states.
|
||||
>
|
||||
> **PETE:** Exactly, exactly. In order to implement that, we communicate it as a fake DOM. What we'll do is rather than throw out the actual browser html and event handlers, we have an internal representation of what the page looks like and then we generate a brand new representation of what we want the page to look like. Then we perform this really, really fast diffing algorithm between those two page representations, DOM representations. Then React will compute the minimum set of DOM mutations it needs to make to bring the page up to date.
|
||||
>
|
||||
> Then to finally get to answer your question, that set of DOM mutations then goes into a queue and we can plug in arbitrary flushing strategies for that. For example, when we originally launched React in open source, every setState would immediately trigger a flush to the DOM. That wasn't part of the contract of setState, but that was just our strategy and it worked pretty well. Then this totally awesome open source contributor Ben Alpert at Khan Academy built a new batching strategy which would basically queue up every single DOM update and state change that happened within an event tick and would execute them in bulk at the end of the event tick.
|
||||
>
|
||||
> [Read the full conversation ...](http://javascriptjabber.com/073-jsj-react-with-pete-hunt-and-jordan-walke/)
|
||||
|
||||
|
||||
## JSXTransformer Trick
|
||||
|
||||
While this is not going to work for all the attributes since they are camelCased in React, this is a pretty cool trick.
|
||||
|
||||
<div style="margin-left: 74px;"><blockquote class="twitter-tweet"><p>Turn any DOM element into a React.js function: JSXTransformer.transform("/** <a href="https://twitter.com/jsx">@jsx</a> React.DOM */" + element.innerHTML).code</p>— Ross Allen (@ssorallen) <a href="https://twitter.com/ssorallen/statuses/377105575441489920">September 9, 2013</a></blockquote></div>
|
||||
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||
|
||||
|
||||
## Remarkable React
|
||||
|
||||
[Stoyan Stefanov](http://www.phpied.com/) gave a talk at [BrazilJS](http://braziljs.com.br/) about React and wrote an article with the content of the presentation. He goes through the difficulties of writting _active apps_ using the DOM API and shows how React handles it.
|
||||
|
||||
> So how does exactly React deal with it internally? Two crazy ideas - virtual DOM and synthetic events.
|
||||
>
|
||||
> You define you components in React. It builds a virtual DOM in JavaScript land which is way more efficient. Then it updates the DOM. (And "virtual DOM" is a very big name for what is simply a JavaScript object with nested key-value pairs)
|
||||
>
|
||||
> Data changes. React computes a diff (in JavaScript land, which is, of course, much more efficient) and updates the single table cell that needs to change. React replicates the state of the virtual DOM into the actual DOM only when and where it's necessary. And does it all at once, in most cases in a single tick of the `requestAnimationFrame()`.
|
||||
>
|
||||
> What about event handlers? They are synthetic. React uses event delegation to listen way at the top of the React tree. So removing a node in the virtual DOM has no effect on the event handling.
|
||||
>
|
||||
> The events are automatically cross-browser (they are React events). They are also much closer to W3C than any browser. That means that for example `e.target` works, no need to look for the event object or checking whether it's `e.target` or `e.srcElement` (IE). Bubbling and capturing phases also work cross browser. React also takes the liberty of making some small fixes, e.g. the event `<input onChange>` fires when you type, not when blur away from the input. And of course, event delegation is used as the most efficient way to handle events. You know that "thou shall use event delegation" is also commonly given advice for making web apps snappy.
|
||||
>
|
||||
> The good thing about the virtual DOM is that it's all in JavaScript land. You build all your UI in JavaScript. Which means it can be rendered on the server side, so you initial view is fast (and any SEO concerns are addressed). Also, if there are especially heavy operations they can be threaded into WebWorkers, which otherwise have no DOM access.
|
||||
>
|
||||
> [Read More ...](http://www.phpied.com/remarkable-react/)
|
||||
|
||||
|
||||
## Markdown in React
|
||||
|
||||
[Ben Alpert](http://benalpert.com/) converted [marked](https://github.com/chjj/marked), a Markdown Javascript implementation, in React: [marked-react](https://github.com/spicyj/marked-react). Even without using JSX, the HTML generation is now a lot cleaner. It is also safer as forgetting a call to `escape` will not introduce an XSS vulnerability.
|
||||
<figure>[](https://github.com/spicyj/marked-react/commit/cb70c9df6542c7c34ede9efe16f9b6580692a457)</figure>
|
||||
|
||||
|
||||
## Unite from BugBusters
|
||||
|
||||
[Renault John Lecoultre](https://twitter.com/renajohn) wrote [Unite](https://www.bugbuster.com/), an interactive tool for analyzing code dynamically using React. It integrates with CodeMirror.
|
||||
<figure>[](https://unite.bugbuster.com/)</figure>
|
||||
|
||||
## #reactjs IRC Logs
|
||||
|
||||
[Vjeux](http://blog.vjeux.com/) re-implemented the display part of the IRC logger in React. Just 130 lines are needed for a performant infinite scroll with timestamps and color-coded author names.
|
||||
|
||||
<iframe width="100%" height="300" src="http://jsfiddle.net/vjeux/QL9tz/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
|
||||
100
docs/_posts/2013-10-3-community-roundup-9.md
Normal file
@@ -0,0 +1,100 @@
|
||||
---
|
||||
title: "Community Round-up #9"
|
||||
layout: post
|
||||
author: Vjeux
|
||||
---
|
||||
|
||||
We organized a React hackathon last week-end in the Facebook Seattle office. 50 people, grouped into 15 teams, came to hack for a day on React. It was a lot of fun and we'll probably organize more in the future.
|
||||
|
||||

|
||||
|
||||
|
||||
## React Hackathon Winner
|
||||
|
||||
[Alex Swan](http://bold-it.com/) implemented [Qu.izti.me](http://qu.izti.me/), a multi-player quiz game. It is real-time via Web Socket and mobile friendly.
|
||||
|
||||
> The game itself is pretty simple. People join the "room" by going to [http://qu.izti.me](http://qu.izti.me/) on their device. Large displays will show a leaderboard along with the game, and small displays (such as phones) will act as personal gamepads. Users will see questions and a choice of answers. The faster you answer, the more points you earn.
|
||||
>
|
||||
> In my opinion, Socket.io and React go together like chocolate and peanut butter. The page was always an accurate representation of the game object.
|
||||
><figure>[](http://bold-it.com/javascript/facebook-react-example/)</figure>
|
||||
>
|
||||
> [Read More...](http://bold-it.com/javascript/facebook-react-example/)
|
||||
|
||||
## JSConf EU Talk: Rethinking Best Practices
|
||||
|
||||
[Pete Hunt](http://www.petehunt.net/) presented React at JSConf EU. He covers three controversial design decisions of React:
|
||||
|
||||
1. Build **components**, not templates
|
||||
2. Re-render the whole app on every update
|
||||
3. Virtual DOM
|
||||
|
||||
The video will be available soon on the [JSConf EU website](http://2013.jsconf.eu/speakers/pete-hunt-react-rethinking-best-practices.html), but in the meantime, here are Pete's slides:
|
||||
|
||||
<figure><iframe src="http://www.slideshare.net/slideshow/embed_code/26589373" width="550" height="450" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" allowfullscreen></iframe></figure>
|
||||
|
||||
|
||||
## Pump - Clojure bindings for React
|
||||
|
||||
[Alexander Solovyov](http://solovyov.net/) has been working on React bindings for ClojureScript. This is really exciting as it is using "native" ClojureScript data structures.
|
||||
|
||||
```ruby
|
||||
(ns your.app
|
||||
(:require-macros [pump.def-macros :refer [defr]])
|
||||
(:require [pump.core]))
|
||||
|
||||
(defr Component
|
||||
:get-initial-state #(identity {:some-value ""})
|
||||
|
||||
[component props state]
|
||||
|
||||
[:div {:class-name "test"} "hello"])
|
||||
```
|
||||
|
||||
[Check it out on GitHub...](https://github.com/piranha/pump)
|
||||
|
||||
|
||||
## JSXHint
|
||||
|
||||
[Todd Kennedy](http://blog.selfassembled.org/) working at [Condé Nast](http://www.condenast.com/) implemented a wrapper on-top of [JSHint](http://www.jshint.com/) that first converts JSX files to JS.
|
||||
|
||||
> A wrapper around JSHint to allow linting of files containg JSX syntax. Accepts glob patterns. Respects your local .jshintrc file and .gitignore to filter your glob patterns.
|
||||
>
|
||||
> ```
|
||||
npm install -g jsxhint
|
||||
```
|
||||
>
|
||||
> [Check it out on GitHub...](https://github.com/CondeNast/JSXHint)
|
||||
|
||||
|
||||
## Turbo React
|
||||
|
||||
[Ross Allen](https://twitter.com/ssorallen) working at [Mesosphere](http://mesosphere.io/) combined [Turbolinks](https://github.com/rails/turbolinks/), a library used by Ruby on Rails to speed up page transition, and React.
|
||||
|
||||
> "Re-request this page" is just a link to the current page. When you click it, Turbolinks intercepts the GET request and fetchs the full page via XHR.
|
||||
>
|
||||
> The panel is rendered with a random panel- class on each request, and the progress bar gets a random widthX class.
|
||||
>
|
||||
> With Turbolinks alone, the entire <body> would be replaced, and transitions would not happen. In this little demo though, React adds and removes classes and text, and the attribute changes are animated with CSS transitions. The DOM is otherwise left intact.
|
||||
><figure>[](https://turbo-react.herokuapp.com/)</figure>
|
||||
>
|
||||
> [Check out the demo...](https://turbo-react.herokuapp.com/)
|
||||
|
||||
|
||||
## Reactive Table
|
||||
|
||||
[Stoyan Stefanov](http://www.phpied.com/) continues his series of blog posts about React. This one is an introduction tutorial on rendering a simple table with React.
|
||||
|
||||
> React is all about components. So let's build one.
|
||||
>
|
||||
> Let's call it Table (to avoid any confusion what the component is about).
|
||||
>
|
||||
> ```javascript
|
||||
var Table = React.createClass({
|
||||
/*stuff goeth here*/
|
||||
});
|
||||
```
|
||||
>
|
||||
> You see that React components are defined using a regular JS object. Some properties and methods of the object such as render() have special meanings, the rest is upforgrabs.
|
||||
>
|
||||
> [Read the full article...](http://www.phpied.com/reactive-table/)
|
||||
|
||||
15
docs/blog/all.html
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Blog
|
||||
layout: default
|
||||
sectionid: blog
|
||||
id: all-posts
|
||||
---
|
||||
|
||||
<section class="content wrap documentationContent nosidebar">
|
||||
<div class="inner-content">
|
||||
<h1>All Posts</h1>
|
||||
{% for page in site.posts %}
|
||||
<p><strong><a href="/react{{ page.url }}">{{ page.title }}</a></strong> on {{ page.date | date: "%B %e, %Y" }} by {{ page.author }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
34
docs/blog/index.html
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: Blog
|
||||
layout: default
|
||||
sectionid: blog
|
||||
---
|
||||
|
||||
<section class="content wrap blogContent">
|
||||
{% include nav_blog.html %}
|
||||
<div class="inner-content">
|
||||
{% for page in paginator.posts %}
|
||||
<div class="post-list-item">
|
||||
<h1><a href="/react{{ page.url }}">{{ page.title }}</a></h1>
|
||||
<p class="meta">{{ page.date | date: "%B %e, %Y" }} by {{ page.author }}</p>
|
||||
<hr />
|
||||
<div class="post">
|
||||
{{ page.content }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="pagination">
|
||||
{% if paginator.previous_page %}
|
||||
<a href="/react/blog/{{ paginator.previous_page_path }}" class="previous">
|
||||
« Previous Page
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if paginator.next_page %}
|
||||
<a href="/react/blog/{{ paginator.next_page_path }}" class="next">
|
||||
Next Page »
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
30
docs/docs/01-why-react.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
id: why-react
|
||||
title: Why React?
|
||||
layout: docs
|
||||
permalink: 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](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)**.
|
||||
|
||||
We built React to solve one problem: **building large applications with data that changes over time**. To do this, React uses two main ideas.
|
||||
|
||||
### Simple
|
||||
|
||||
Simply express how your app should look at any given point in time, and React will automatically manage all UI updates when your underlying data changes.
|
||||
|
||||
### Declarative
|
||||
|
||||
When the data changes, React conceptually hits the "refresh" button, and knows to only update the changed parts.
|
||||
|
||||
## Build Composable Components
|
||||
|
||||
React is all about building reusable components. In fact, with React the *only* thing you do is build components. Since they're so encapsulated, components make code reuse, testing, and separation of concerns easy.
|
||||
|
||||
## Give It Five Minutes
|
||||
|
||||
React challenges a lot of conventional wisdom, and at first glance some of the ideas may seem crazy. [Give it five minutes](http://37signals.com/svn/posts/3124-give-it-five-minutes) while reading this guide; those crazy ideas have worked for building thousands of components both inside and outside of Facebook and Instagram.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more about our motivations behind building React in [this blog post](http://facebook.github.io/react/blog/2013/06/05/why-react.html).
|
||||
91
docs/docs/02-displaying-data.md
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
id: displaying-data
|
||||
title: Displaying Data
|
||||
layout: docs
|
||||
permalink: displaying-data.html
|
||||
prev: why-react.html
|
||||
next: jsx-in-depth.html
|
||||
---
|
||||
|
||||
The most basic thing you can do with a UI is display some data. React makes it easy to display data and automatically keeps the interface up-to-date when the data changes.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
Let's look at a really simple example. Create a `hello-react.html` file with the following code:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello React</title>
|
||||
<script src="http://fb.me/react-{{site.react_version}}.min.js"></script>
|
||||
<script src="http://fb.me/JSXTransformer-{{site.react_version}}.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
<script type="text/jsx">
|
||||
|
||||
// ** Your code goes here! **
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
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 JS:
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
|
||||
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() {
|
||||
React.renderComponent(
|
||||
<HelloWorld date={new Date()} />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
}, 500);
|
||||
```
|
||||
|
||||
|
||||
## Reactive Updates
|
||||
|
||||
Open `hello-react.html` in a web browser and type your name into the text field. Notice that React is only changing the time string in the UI — any input you put in the text field remains, even though you haven't written any code to manage this behavior. React figures it out for you and does the right thing.
|
||||
|
||||
The way we are able to figure this out is that React does not manipulate the DOM unless it needs to. **It uses a fast, internal mock DOM to perform diffs and computes the most efficient DOM mutation for you.**
|
||||
|
||||
The inputs to this component are called `props` — short for "properties". They're passed as attributes in JSX syntax. You should think of these as immutable within the component, that is, **never write to `this.props`**.
|
||||
|
||||
|
||||
## Components are Just Like Functions
|
||||
|
||||
React components are very simple. You can think of them as simple function that take in `props` and `state` (discussed later) and render HTML. Because they're so simple, it makes them very easy to reason about.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> **One limitation**: React components can only render a single root node. If you want to return multiple nodes they *must* be wrapped in a single root.
|
||||
|
||||
|
||||
## JSX Syntax
|
||||
|
||||
We strongly believe that components are the right way to separate concerns rather than "templates" and "display logic." We think that markup and the code that generates it are intimately tied together. Additionally, display logic is often very complex and using template languages to express it becomes cumbersome.
|
||||
|
||||
We've found that the best solution for this problem is to generate markup directly from the JavaScript code such that you can use all of the expressive power of a real programming language to build UIs. In order to make this easier, we've added a very simple, **optional** HTML-like syntax for the function calls that generate markup called JSX.
|
||||
|
||||
**JSX lets you write JavaScript function calls with HTML syntax.** To generate a link in React using pure JavaScript you'd write: `React.DOM.a({href: 'http://facebook.github.io/react/'}, 'Hello React!')`. With JSX this becomes `<a href="http://facebook.github.io/react/">Hello React!</a>`. We've found this has made building React apps easier and designers tend to prefer the syntax, but everyone has their own workflow, so **JSX is not required to use React.**
|
||||
|
||||
JSX is very small; the "hello, world" example above uses every feature of JSX. To learn more about it, see [JSX in depth](./jsx-in-depth.html). Or see the transform in action in [our live JSX compiler](/react/jsx-compiler.html).
|
||||
|
||||
JSX is similar to HTML, but not exactly the same. See [JSX gotchas](./jsx-gotchas.html) for some key differences.
|
||||
|
||||
The easiest way to get started with JSX is to use the in-browser `JSXTransformer`. We strongly recommend that you don't use this in production. You can precompile your code using our command-line [react-tools](http://npmjs.org/package/react-tools) package.
|
||||
@@ -1,29 +1,43 @@
|
||||
---
|
||||
id: docs-syntax
|
||||
title: JSX Syntax
|
||||
description: Writing JavaScript with XML syntax.
|
||||
id: jsx-in-depth
|
||||
title: JSX in Depth
|
||||
layout: docs
|
||||
prev: common-questions.html
|
||||
next: component-basics.html
|
||||
permalink: jsx-in-depth.html
|
||||
prev: displaying-data.html
|
||||
next: jsx-gotchas.html
|
||||
---
|
||||
|
||||
JSX is a JavaScript XML syntax extension recommended (but not required) for use
|
||||
JSX is a JavaScript XML syntax transform recommended for use
|
||||
with React.
|
||||
|
||||
JSX makes code that deeply nests React components more readable, and writing it
|
||||
feels like writing HTML. React documentation examples make use of JSX.
|
||||
|
||||
## Why JSX?
|
||||
|
||||
React works out of the box without JSX. Simply construct your markup using the
|
||||
functions on `React.DOM`. For example, here's how to construct a simple link:
|
||||
|
||||
```javascript
|
||||
var link = React.DOM.a({href: 'http://facebook.github.io/react'}, 'React');
|
||||
```
|
||||
|
||||
We recommend using JSX for many reasons:
|
||||
|
||||
* It's easier to visualize the structure of the DOM.
|
||||
* Designers are more comfortable making changes.
|
||||
* It's familiar for those who have used MXML or XAML.
|
||||
|
||||
|
||||
## The Transform
|
||||
|
||||
JSX transforms XML-like syntax into native JavaScript. It turns XML elements and
|
||||
attributes into function calls and objects, respectively.
|
||||
JSX transforms from an XML-like syntax into native JavaScript. XML elements and
|
||||
attributes are transformed into function calls and objects, respectively.
|
||||
|
||||
```javascript
|
||||
var Nav;
|
||||
// Input (JSX):
|
||||
var app = <Nav color="blue" />;
|
||||
// Output (JS):
|
||||
var app = Nav({color:'blue'});
|
||||
var app = Nav({color:"blue"});
|
||||
```
|
||||
|
||||
Notice that in order to use `<Nav />`, the `Nav` variable must be in scope.
|
||||
@@ -35,27 +49,31 @@ var Nav, Profile;
|
||||
// Input (JSX):
|
||||
var app = <Nav color="blue"><Profile>click</Profile></Nav>;
|
||||
// Output (JS):
|
||||
var app = Nav({color:'blue'}, Profile({}, 'click'));
|
||||
var app = Nav({color:"blue"}, Profile(null, "click"));
|
||||
```
|
||||
|
||||
The [Getting Started](getting-started.html) guide shows how to setup JSX
|
||||
compilation.
|
||||
Use the [JSX Compiler](/react/jsx-compiler.html) to try out JSX and see how it
|
||||
desugars into native JavaScript.
|
||||
|
||||
If you want to use JSX, the [Getting Started](getting-started.html) guide shows
|
||||
how to setup compilation.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> Details about the code transform are given here to increase understanding, but
|
||||
> your code should not rely on these implementation details.
|
||||
|
||||
|
||||
## React and JSX
|
||||
|
||||
React and JSX are independent technologies, but JSX was primarily built with
|
||||
React in mind. The two valid uses of JSX are:
|
||||
|
||||
- To construct instances of React DOM components (`React.DOM.*`).
|
||||
- To construct instances of composite components created with
|
||||
* To construct instances of React DOM components (`React.DOM.*`).
|
||||
* To construct instances of composite components created with
|
||||
`React.createClass()`.
|
||||
|
||||
**React DOM Components**
|
||||
### React DOM Components
|
||||
|
||||
To construct a `<div>` is to create a variable that refers to `React.DOM.div`.
|
||||
|
||||
@@ -64,7 +82,7 @@ var div = React.DOM.div;
|
||||
var app = <div className="appClass">Hello, React!</div>;
|
||||
```
|
||||
|
||||
**React Component Components**
|
||||
### React Composite Components
|
||||
|
||||
To construct an instance of a composite component, create a variable that
|
||||
references the class.
|
||||
@@ -74,7 +92,7 @@ var MyComponent = React.createClass({/*...*/});
|
||||
var app = <MyComponent someProperty={true} />;
|
||||
```
|
||||
|
||||
See [Component Basics](component-basics.html) to learn more about components.
|
||||
See [Multiple Components](multiple-components.html) to learn more about using composite components.
|
||||
|
||||
> Note:
|
||||
>
|
||||
@@ -97,7 +115,7 @@ var Nav;
|
||||
// Input (JSX):
|
||||
var tree = <Nav><span /></Nav>;
|
||||
// Output (JS):
|
||||
var tree = Nav({}, React.DOM.span({}));
|
||||
var tree = Nav(null, React.DOM.span(null));
|
||||
```
|
||||
|
||||
> Remember:
|
||||
@@ -108,7 +126,7 @@ var tree = Nav({}, React.DOM.span({}));
|
||||
|
||||
## JavaScript Expressions
|
||||
|
||||
#### Attribute Expressions
|
||||
### Attribute Expressions
|
||||
|
||||
To use a JavaScript expression as an attribute value, wrap the expression in a
|
||||
pair of curly braces (`{}`) instead of quotes (`""`).
|
||||
@@ -120,7 +138,7 @@ var person = <Person name={window.isLoggedIn ? window.name : ''} />;
|
||||
var person = Person({name: window.isLoggedIn ? window.name : ''});
|
||||
```
|
||||
|
||||
#### Child Expressions
|
||||
### Child Expressions
|
||||
|
||||
Likewise, JavaScript expressions may be used to express children:
|
||||
|
||||
@@ -128,24 +146,39 @@ Likewise, JavaScript expressions may be used to express children:
|
||||
// Input (JSX):
|
||||
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
|
||||
// Output (JS):
|
||||
var content = Container({}, window.isLoggedIn ? <Nav /> : <Login />);
|
||||
var content = Container(null, window.isLoggedIn ? Nav(null) : Login(null));
|
||||
```
|
||||
|
||||
### Comments
|
||||
|
||||
It's easy to add comments within your JSX; they're just JS expressions:
|
||||
|
||||
```javascript
|
||||
var content = <Container>{/* this is a comment */}<Nav /></Container>;
|
||||
```
|
||||
|
||||
## Tooling
|
||||
|
||||
Beyond the compilation step, JSX does not require any special tools.
|
||||
|
||||
- Many editors already include reasonable support for JSX (Vim, Emacs js2-mode).
|
||||
- Linting provides accurate line numbers after compiling without sourcemaps.
|
||||
- Elements use standard scoping so linters can find usage of out-of-scope
|
||||
* Many editors already include reasonable support for JSX (Vim, Emacs js2-mode).
|
||||
* JSX syntax highlighting is available for Sublime Text and other editors
|
||||
that support `*.tmLanguage` using the third-party
|
||||
[`JavaScript (JSX).tmLanguage`][1].
|
||||
* Linting provides accurate line numbers after compiling without sourcemaps.
|
||||
* Elements use standard scoping so linters can find usage of out-of-scope
|
||||
components.
|
||||
|
||||
[1]: https://github.com/yungsters/sublime/blob/master/tmLanguage/JavaScript%20(JSX).tmLanguage
|
||||
|
||||
## Prior Work
|
||||
|
||||
JSX is similar to several other JavaScript embedded XML language
|
||||
proposals/projects. Some of the features of JSX that distinguish it from similar
|
||||
efforts include:
|
||||
|
||||
- JSX is a simple syntactic transform.
|
||||
- JSX neither provides nor requires a runtime library.
|
||||
- JSX does not alter or add to the semantics of JavaScript.
|
||||
* JSX is a simple syntactic transform.
|
||||
* JSX neither provides nor requires a runtime library.
|
||||
* JSX does not alter or add to the semantics of JavaScript.
|
||||
|
||||
JSX is similar to HTML, but not exactly the same. See [JSX gotchas](./jsx-gotchas.html) for some key differences.
|
||||
77
docs/docs/02.2-jsx-gotchas.md
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
id: jsx-gotchas
|
||||
title: JSX Gotchas
|
||||
layout: docs
|
||||
permalink: jsx-gotchas.html
|
||||
prev: jsx-in-depth.html
|
||||
next: interactivity-and-dynamic-uis.html
|
||||
---
|
||||
|
||||
JSX looks like HTML but there are some important differences you may run into.
|
||||
|
||||
|
||||
## Whitespace Removal
|
||||
|
||||
JSX doesn't follow the same whitespace elimination rules as HTML. JSX removes all whitespace between two curly braces expressions. If you want to have whitespace, simply add `{' '}`.
|
||||
|
||||
```javascript
|
||||
<div>{this.props.name} {' '} {this.props.surname}</div>
|
||||
```
|
||||
|
||||
Follow [Issue #65](https://github.com/facebook/react/issues/65) for discussion on this behavior.
|
||||
|
||||
|
||||
## HTML Entities
|
||||
|
||||
You can insert HTML entities within literal text in JSX:
|
||||
|
||||
```javascript
|
||||
<div>First · Second</div>
|
||||
```
|
||||
|
||||
If you want to display an HTML entity within dynamic content, you will run into double escaping issues as React escapes all the strings you are displaying in order to prevent a wide range of XSS attacks by default.
|
||||
|
||||
```javascript
|
||||
// Bad: It displays "First · Second"
|
||||
<div>{'First · Second'}</div>
|
||||
```
|
||||
|
||||
There are various ways to work-around this issue. The easiest one is to write unicode character directly in Javascript. You need to make sure that the file is saved as UTF-8 and that the proper UTF-8 directives are set so the browser will display it correctly.
|
||||
|
||||
```javascript
|
||||
<div>{'First · Second'}</div>
|
||||
```
|
||||
|
||||
A safer alternative is to find the [unicode number corresponding to the entity](http://www.fileformat.info/info/unicode/char/b7/index.htm) and use it inside of a JavaScript string.
|
||||
|
||||
```javascript
|
||||
<div>{'First \u00b7 Second'}</div>
|
||||
<div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
|
||||
```
|
||||
|
||||
You can use mixed arrays with strings and JSX elements.
|
||||
|
||||
```javascript
|
||||
<div>{['First ', <span>·</span>, ' Second']}</div>
|
||||
```
|
||||
|
||||
As a last resort, you always have the ability to insert raw HTML.
|
||||
|
||||
```javascript
|
||||
<div dangerouslySetInnerHTML={{'{{'}}__html: 'First · Second'}} />
|
||||
```
|
||||
|
||||
|
||||
## Custom HTML Attributes
|
||||
|
||||
If you pass properties to native HTML elements that do not exist in the HTML specification, React will not render them. If you want to use a custom attribute, you should prefix it with `data-`.
|
||||
|
||||
```javascript
|
||||
<div data-custom-attribute="foo" />
|
||||
```
|
||||
|
||||
[Web Accessibility](http://www.w3.org/WAI/intro/aria) attributes starting with `aria-` will be rendered properly.
|
||||
|
||||
```javascript
|
||||
<div aria-hidden={true} />
|
||||
```
|
||||
89
docs/docs/03-interactivity-and-dynamic-uis.md
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
id: interactivity-and-dynamic-uis
|
||||
title: Interactivity and Dynamic UIs
|
||||
layout: docs
|
||||
permalink: interactivity-and-dynamic-uis.html
|
||||
prev: jsx-gotchas.html
|
||||
next: multiple-components.html
|
||||
---
|
||||
|
||||
You've already [learned how to display data](./displaying-data.html) with React. Now let's look at how to make our UIs interactive.
|
||||
|
||||
|
||||
## A Simple Example
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
|
||||
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 ? 'like' : 'unlike';
|
||||
return (
|
||||
<p onClick={this.handleClick}>
|
||||
You {text} this. Click to toggle.
|
||||
</p>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.renderComponent(
|
||||
<LikeButton />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Event Handling and Synthetic Events
|
||||
|
||||
With React you simply pass your event handler as a camelCased prop similar to how you'd do it in normal HTML. React ensures that all events behave identically in IE8 and above by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with [the W3C spec](http://www.w3.org/TR/DOM-Level-3-Events/), regardless of which browser you're using.
|
||||
|
||||
If you'd like to use React on a touch device (i.e. a phone or tablet), simply call `React.initializeTouchEvents(true);` to turn them on.
|
||||
|
||||
|
||||
## Under the Hood: autoBind and Event Delegation
|
||||
|
||||
Under the hood React does a few things to keep your code performant and easy to understand.
|
||||
|
||||
**Autobinding:** When creating callbacks in JavaScript you usually need to explicitly bind a method to its instance such that the value of `this` is correct. With React, every method is automatically bound to its component instance. React caches the bound method such that it's extremely CPU and memory efficient. It's also less typing!
|
||||
|
||||
**Event delegation:** React doesn't actually attach event handlers to the nodes themselves. When React starts up, it starts listening for all events at the top level using a single event listener. When a component is mounted or unmounted, the event handlers are simply added or removed from an internal mapping. When an event occurs, React knows how to dispatch it using this mapping. When there are no event handlers left in the mapping, React's event handlers are simple no-ops. To learn more about why this is fast, see [David Walsh's excellent blog post](http://davidwalsh.name/event-delegate).
|
||||
|
||||
|
||||
## Components are Just State Machines
|
||||
|
||||
React thinks of UIs as simple state machines. By thinking of a UI as being in various states and rendering those states, it's easy to keep your UI consistent.
|
||||
|
||||
In React, you simply update a component's state, and then render a new UI based on this new state. React takes care of updating the DOM for you in the most efficient way.
|
||||
|
||||
|
||||
## How State Works
|
||||
|
||||
A common way to inform React of a data change is by calling `setState(data, callback)`. This method merges `data` into `this.state` and re-renders the component. When the component finishes re-rendering, the optional `callback` is called. Most of the time you'll never need to provide a `callback` since React will take care of keeping your UI up-to-date for you.
|
||||
|
||||
|
||||
## What Components Should Have State?
|
||||
|
||||
Most of your components should simply take some data from `props` and render it. However, sometimes you need to respond to user input, a server request or the passage of time. For this you use state.
|
||||
|
||||
**Try to keep as many of your components as possible stateless.** By doing this you'll isolate the state to its most logical place and minimize redundancy, making it easier to reason about your application.
|
||||
|
||||
A common pattern is to create several stateless components that just render data, and have a stateful component above them in the hierarchy that passes its state to its children via `props`. The stateful component encapsulates all of the interaction logic, while the stateless components take care of rendering data in a declarative way.
|
||||
|
||||
|
||||
## What *Should* Go in State?
|
||||
|
||||
**State should contain data that a component's event handlers may change to trigger a UI update.** In real apps this data tends to be very small and JSON-serializable. When building a stateful component, think about the minimal possible representation of its state, and only store those properties in `this.state`. Inside of `render()` simply compute any other information you need based on this state. You'll find that thinking about and writing applications in this way tends to lead to the most correct application, since adding redundant or computed values to state means that you need to explicitly keep them in sync rather than rely on React computing them for you.
|
||||
|
||||
## What *Shouldn't* Go in State?
|
||||
|
||||
`this.state` should only contain the minimal amount of data needed to represent your UI's state. As such, it should not contain:
|
||||
|
||||
* **Computed data:** Don't worry about precomputing values based on state — it's easier to ensure that your UI is consistent if you do all computation within `render()`. For example, if you have an array of list items in state and you want to render the count as a string, simply render `this.state.listItems.length + ' list items'` in your `render()` method rather than storing it on state.
|
||||
* **React components:** Build them in `render()` based on underlying props and state.
|
||||
* **Duplicated data from props:** Try to use props as the source of truth where possible. Because props can change over time, it's appropriate to store props in state to be able to know its previous values.
|
||||
151
docs/docs/04-multiple-components.md
Normal file
@@ -0,0 +1,151 @@
|
||||
---
|
||||
id: multiple-components
|
||||
title: Multiple Components
|
||||
layout: docs
|
||||
permalink: multiple-components.html
|
||||
prev: interactivity-and-dynamic-uis.html
|
||||
next: reusable-components.html
|
||||
---
|
||||
|
||||
So far, we've looked at how to write a single component to display data and handle user input. Next let's examine one of React's finest features: composability.
|
||||
|
||||
|
||||
## Motivation: Separation of Concerns
|
||||
|
||||
By building modular components that reuse other components with well-defined interfaces, you get much of the same benefits that you get by using functions or classes. Specifically you can *separate the different concerns* of your app however you please simply by building new components. By building a custom component library for your application, you are expressing your UI in a way that best fits your domain.
|
||||
|
||||
|
||||
## Composition Example
|
||||
|
||||
Let's create a simple Avatar component which shows a profile picture and username using the Facebook Graph API.
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
|
||||
var Avatar = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ProfilePic username={this.props.username} />
|
||||
<ProfileLink username={this.props.username} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfilePic = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<img src={'http://graph.facebook.com/' + this.props.username + '/picture'} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfileLink = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<a href={'http://www.facebook.com/' + this.props.username}>
|
||||
{this.props.username}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.renderComponent(
|
||||
<Avatar username="pwh" />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Ownership
|
||||
|
||||
In the above example, instances of `Avatar` *own* instances of `ProfilePic` and `ProfileLink`. In React, **an owner is the component that sets the `props` of other components**. More formally, if a component `X` is created in component `Y`'s `render()` method, it is said that `X` is *owned by* `Y`. As discussed earlier, a component cannot mutate its `props` — they are always consistent with what its owner sets them to. This key property leads to UIs that are guaranteed to be consistent.
|
||||
|
||||
It's important to draw a distinction between the owner-ownee relationship and the parent-child relationship. The owner-ownee relationship is specific to React, while the parent-child relationship is simply the one you know and love from the DOM. In the example above, `Avatar` owns the `div`, `ProfilePic` and `ProfileLink` instances, and `div` is the **parent** (but not owner) of the `ProfilePic` and `ProfileLink` instances.
|
||||
|
||||
|
||||
## Children
|
||||
|
||||
When you create a React component instance, you can include additional React components or JavaScript expressions between the opening and closing tags like this:
|
||||
|
||||
```javascript
|
||||
<Parent><Child /></Parent>
|
||||
```
|
||||
|
||||
`Parent` can read its children by accessing the special `this.props.children` prop.
|
||||
|
||||
|
||||
### Child Reconciliation
|
||||
|
||||
**Reconciliation is the process by which React updates the DOM with each new render pass.** In general, children are reconciled according to the order in which they are rendered. For example, suppose two render passes generate the following respective markup:
|
||||
|
||||
```html
|
||||
// Render Pass 1
|
||||
<Card>
|
||||
<p>Paragraph 1</p>
|
||||
<p>Paragraph 2</p>
|
||||
</Card>
|
||||
// Render Pass 2
|
||||
<Card>
|
||||
<p>Paragraph 2</p>
|
||||
</Card>
|
||||
```
|
||||
|
||||
Intuitively, `<p>Paragraph 1</p>` was removed. Instead, React will reconcile the DOM by changing the text content of the first child and destroying the last child. React reconciles according to the *order* of the children.
|
||||
|
||||
|
||||
### Stateful Children
|
||||
|
||||
For most components, this is not a big deal. However, for stateful components that maintain data in `this.state` across render passes, this can be very problematic.
|
||||
|
||||
In most cases, this can be sidestepped by hiding elements instead of destroying them:
|
||||
|
||||
```html
|
||||
// Render Pass 1
|
||||
<Card>
|
||||
<p>Paragraph 1</p>
|
||||
<p>Paragraph 2</p>
|
||||
</Card>
|
||||
// Render Pass 2
|
||||
<Card>
|
||||
<p style={{'{{'}}display: 'none'}}>Paragraph 1</p>
|
||||
<p>Paragraph 2</p>
|
||||
</Card>
|
||||
```
|
||||
|
||||
|
||||
### Dynamic Children
|
||||
|
||||
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;
|
||||
return (
|
||||
<ol>
|
||||
{this.results.map(function(result) {
|
||||
return <li key={result.id}>{result.text}</li>;
|
||||
})}
|
||||
</ol>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
When React reconciles the keyed children, it will ensure that any child with `key` will be reordered (instead of clobbered) or destroyed (instead of reused).
|
||||
|
||||
|
||||
## Data Flow
|
||||
|
||||
In React, data flows from owner to owned component through `props` as discussed above. This is effectively one-way data binding: owners bind their owned component's props to some value the owner has computed based on its `props` or `state`. Since this process happens recursively, data changes are automatically reflected everywhere they are used.
|
||||
|
||||
|
||||
## A Note on Performance
|
||||
|
||||
You may be thinking that it's expensive to react to changing data if there are a large number of nodes under an owner. The good news is that JavaScript is fast and `render()` methods tend to be quite simple, so in most applications this is extremely fast. Additionally, the bottleneck is almost always the DOM mutation and not JS execution and React will optimize this for you using batching and change detection.
|
||||
|
||||
However, sometimes you really want to have fine-grained control over your performance. In that case, simply override `shouldComponentUpdate()` to return false when you want React to skip processing of a subtree. See [the React reference docs](component-specs.html) for more information.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> If `shouldComponentUpdate()` returns false when data has actually changed, React can't keep your UI in sync. Be sure you know what you're doing while using it, and only use this function when you have a noticeable performance problem. Don't underestimate how fast JavaScript is relative to the DOM.
|
||||
143
docs/docs/05-reusable-components.md
Normal file
@@ -0,0 +1,143 @@
|
||||
---
|
||||
id: reusable-components
|
||||
title: Reusable Components
|
||||
layout: docs
|
||||
permalink: reusable-components.html
|
||||
prev: multiple-components.html
|
||||
next: forms.html
|
||||
---
|
||||
|
||||
When designing interfaces, break down the common design elements (buttons, form fields, layout components, etc) into reusable components with well-defined interfaces. That way, the next time you need to build some UI you can write much less code, which means faster development time, less bugs, and less bytes down the wire.
|
||||
|
||||
|
||||
## 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, an error will be thrown. Here is an example documenting the different validators provided:
|
||||
|
||||
```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,
|
||||
|
||||
// You can ensure that your prop is limited to specific values by treating
|
||||
// it as an enum.
|
||||
optionalEnum: React.PropTypes.oneOf(['News','Photos']),
|
||||
|
||||
// You can also declare that a prop is an instance of a class. This uses
|
||||
// JS's instanceof operator.
|
||||
someClass: React.PropTypes.instanceOf(SomeClass),
|
||||
|
||||
// You can chain any of the above with isRequired to make sure an error is
|
||||
// thrown if the prop isn't provided.
|
||||
requiredFunc: React.PropTypes.func.isRequired
|
||||
|
||||
// You can also specify a custom validator.
|
||||
customProp: function(props, propName, componentName) {
|
||||
if (!/matchme/.test(props[propName])) {
|
||||
throw new Error('Validation failed!')
|
||||
}
|
||||
}
|
||||
},
|
||||
/* ... */
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Default Prop Values
|
||||
|
||||
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'
|
||||
};
|
||||
}
|
||||
/* ... */
|
||||
});
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## Transferring Props: A Shortcut
|
||||
|
||||
A common type of React component is one that extends a basic HTML 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. React provides `transferPropsTo()` to do just this.
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
|
||||
var CheckLink = React.createClass({
|
||||
render: function() {
|
||||
// transferPropsTo() will take any props passed to CheckLink
|
||||
// and copy them to <a>
|
||||
return this.transferPropsTo(<a>{'√ '}{this.props.children}</a>);
|
||||
}
|
||||
});
|
||||
|
||||
React.renderComponent(
|
||||
<CheckLink href="javascript:alert('Hello, world!');">
|
||||
Click here!
|
||||
</CheckLink>,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Mixins
|
||||
|
||||
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](http://en.wikipedia.org/wiki/Cross-cutting_concern). React provides `mixins` to solve this problem.
|
||||
|
||||
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](./working-with-the-browser.html) 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.
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
|
||||
var SetIntervalMixin = {
|
||||
componentWillMount: function() {
|
||||
this.intervals = [];
|
||||
},
|
||||
setInterval: function() {
|
||||
this.intervals.push(setInterval.apply(null, arguments));
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
this.intervals.map(clearInterval);
|
||||
}
|
||||
};
|
||||
|
||||
var TickTock = React.createClass({
|
||||
mixins: [SetIntervalMixin], // Use the mixin
|
||||
getInitialState: function() {
|
||||
return {seconds: 0};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.setInterval(this.tick, 1000); // Call a method on the mixin
|
||||
},
|
||||
tick: function() {
|
||||
this.setState({seconds: this.state.seconds + 1});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<p>
|
||||
React has been running for {this.state.seconds} seconds.
|
||||
</p>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.renderComponent(
|
||||
<TickTock />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
132
docs/docs/06-forms.md
Normal file
@@ -0,0 +1,132 @@
|
||||
---
|
||||
id: forms
|
||||
title: Forms
|
||||
layout: docs
|
||||
permalink: forms.html
|
||||
prev: reusable-components.html
|
||||
next: working-with-the-browser.html
|
||||
---
|
||||
|
||||
Form components such as `<input>`, `<textarea>`, and `<option>` differ from other native components because they can be mutated via user interactions. These components provide interfaces that make it easier to manage forms in response to user interactions.
|
||||
|
||||
|
||||
## Interactive Props
|
||||
|
||||
Form components support a few props that are affected via user interactions:
|
||||
|
||||
* `value`, supported by `<input>` and `<textarea>` components.
|
||||
* `checked`, supported by `<input>` components of type `checkbox` or `radio`.
|
||||
* `selected`, supported by `<option>` components.
|
||||
|
||||
In HTML, the value of `<textarea>` is set via children. In React, you should use `value` instead.
|
||||
|
||||
Form components allow listening for changes by setting a callback to the `onChange` prop. The `onChange` prop works across browsers to fire in response to user interactions when:
|
||||
|
||||
* The `value` of `<input>` or `<textarea>` changes.
|
||||
* The `checked` state of `<input>` changes.
|
||||
* The `selected` state of `<option>` changes.
|
||||
|
||||
Like all DOM events, the `onChange` prop is supported on all native components and can be used to listen to bubbled change events.
|
||||
|
||||
|
||||
## Controlled Components
|
||||
|
||||
An `<input>` with `value` set is a *controlled* component. In a controlled `<input>`, the value of the rendered element will always reflect the `value` prop. For example:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
return <input type="text" value="Hello!" />;
|
||||
}
|
||||
```
|
||||
|
||||
This will render an input that always has a value of `Hello!`. Any user input will have no effect on the rendered element because React has declared the value to be `Hello!`. If you wanted to update the value in response to user input, you could use the `onChange` event:
|
||||
|
||||
```javascript
|
||||
getInitialState: function() {
|
||||
return {value: 'Hello!'};
|
||||
},
|
||||
handleChange: function(event) {
|
||||
this.setState({value: event.target.value});
|
||||
},
|
||||
render: function() {
|
||||
var value = this.state.value;
|
||||
return <input type="text" value={value} onChange={this.handleChange} />;
|
||||
}
|
||||
```
|
||||
|
||||
In this example, we are simply accepting the newest 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) {
|
||||
this.setState({value: event.target.value.substr(0, 140)});
|
||||
}
|
||||
```
|
||||
|
||||
This would accept user input but truncate the value to the first 140 characters.
|
||||
|
||||
|
||||
## Uncontrolled Components
|
||||
|
||||
An `<input>` that does not supply a `value` (or sets it to `null`) is an *uncontrolled* component. In an uncontrolled `<input>`, the value of the rendered element will reflect the user's input. For example:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
return <input type="text" />;
|
||||
}
|
||||
```
|
||||
|
||||
This will render an input that starts off with an empty value. Any user input will be immediately reflected by the rendered element. If you wanted to listen to updates to the value, you could use the `onChange` event just like you can with controlled components.
|
||||
|
||||
If you want to initialize the component with a non-empty value, you can supply a `defaultValue` prop. For example:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
return <input type="text" defaultValue="Hello!" />;
|
||||
}
|
||||
```
|
||||
|
||||
This example will function much like the **Controlled Components** example above.
|
||||
|
||||
Likewise, `<input>` supports `defaultChecked` and `<option>` supports `defaultSelected`.
|
||||
|
||||
|
||||
## Advanced Topics
|
||||
|
||||
|
||||
### Why Controlled Components?
|
||||
|
||||
Using form components such as `<input>` in React presents a challenge that is absent when writing traditional form HTML. For example, in HTML:
|
||||
|
||||
```html
|
||||
<input type="text" name="title" value="Untitled" />
|
||||
```
|
||||
|
||||
This renders an input *initialized* with the value, `Untitled`. When the user updates the input, the node's value *property* will change. However, `node.getAttribute('value')` will still return the value used at initialization time, `Untitled`.
|
||||
|
||||
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() {
|
||||
return <input type="text" name="title" value="Untitled" />;
|
||||
}
|
||||
```
|
||||
|
||||
Since this method describes the view at any point in time, the value of the text input should *always* be `Untitled`.
|
||||
|
||||
|
||||
### Why Textarea Value?
|
||||
|
||||
In HTML, the value of `<textarea>` is usually set using its children:
|
||||
|
||||
```html
|
||||
<!-- counterexample: DO NOT DO THIS! -->
|
||||
<textarea name="description">This is the description.</textarea>
|
||||
```
|
||||
|
||||
For HTML, this easily allows developers to supply multiline values. However, since React is JavaScript, we do not have string limitations and can use `\n` if we want newlines. In a world where we have `value` and `defaultValue`, it is ambiguous what role children play. For this reason, you should not use children when setting `<textarea>` values:
|
||||
|
||||
```javascript
|
||||
<textarea name="description" value="This is a description." />
|
||||
```
|
||||
|
||||
If you *do* decide to use children, they will behave like `defaultValue`.
|
||||
134
docs/docs/07-working-with-the-browser.md
Normal file
@@ -0,0 +1,134 @@
|
||||
---
|
||||
id: working-with-the-browser
|
||||
title: Working With the Browser
|
||||
layout: docs
|
||||
permalink: working-with-the-browser.html
|
||||
prev: forms.html
|
||||
next: more-about-refs.html
|
||||
---
|
||||
|
||||
React provides powerful abstractions that free you from touching the DOM directly in most cases, but sometimes you simply need to access the underlying API, perhaps to work with a third-party library or existing code.
|
||||
|
||||
|
||||
## The Mock DOM
|
||||
|
||||
React is so fast because it never talks to the DOM directly. React maintains a fast in-memory representation of the DOM. `render()` methods return a *description* of the DOM, and React can diff this description with the in-memory representation to compute the fastest way to update the browser.
|
||||
|
||||
Additionally, React implements a full synthetic event system such that all event objects are guaranteed to conform to the W3C spec despite browser quirks, and everything bubbles consistently and in a performant way cross-browser. You can even use some HTML5 events in IE8!
|
||||
|
||||
Most of the time you should stay within React's "faked browser" world since it's more performant and easier to reason about. However, sometimes you simply need to access the underlying API, perhaps to work with a third-party library like a jQuery plugin. React provides escape hatches for you to use the underlying DOM API directly.
|
||||
|
||||
|
||||
## Refs and getDOMNode()
|
||||
|
||||
To interact with the browser, you'll need a reference to a DOM node. Every mounted React component has a `getDOMNode()` function which you can call to get a reference to it.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> `getDOMNode()` only works on mounted components (that is, components that have been placed in the DOM). If you try to call this on a component that has not been mounted yet (like calling `getDOMNode()` in `render()` on a component that has yet to be created) an exception will be thrown.
|
||||
|
||||
In order to get a reference to a React component, you can either use `this` to get the current React component, or you can use refs to refer to a component you own. They work like this:
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// Explicitly focus the text input using the raw DOM API.
|
||||
this.refs.myTextInput.getDOMNode().focus();
|
||||
},
|
||||
render: function() {
|
||||
// The ref attribute adds a reference to the component to
|
||||
// this.refs when the component is mounted.
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref="myTextInput" />
|
||||
<input
|
||||
type="button"
|
||||
value="Focus the text input"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.renderComponent(
|
||||
<MyComponent />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## More About Refs
|
||||
|
||||
To learn more about refs, including ways to use them effectively, see our [more about refs](./more-about-refs.html) documentation.
|
||||
|
||||
|
||||
## Component Lifecycle
|
||||
|
||||
Components have three main parts of their lifecycle:
|
||||
|
||||
* **Mounting:** A component is being inserted into the DOM.
|
||||
* **Updating:** A component is being re-rendered to determine if the DOM should be updated.
|
||||
* **Unmounting:** A component is being removed from the DOM.
|
||||
|
||||
React provides lifecycle methods that you can specify to hook into this process. We provide **will** methods, which are called right before something happens, and **did** methods which are called right after something happens.
|
||||
|
||||
|
||||
### Mounting
|
||||
|
||||
* `getInitialState(): object` is invoked before a component is mounted. Stateful components should implement this and return the initial state data.
|
||||
* `componentWillMount()` is invoked immediately before mounting occurs.
|
||||
* `componentDidMount(DOMElement rootNode)` is invoked immediately after mounting occurs. Initialization that requires DOM nodes should go here.
|
||||
|
||||
|
||||
### Updating
|
||||
|
||||
* `componentWillReceiveProps(object nextProps)` is invoked when a mounted component receives new props. This method should be used to compare `this.props` and `nextProps` to perform state transitions using `this.setState()`.
|
||||
* `shouldComponentUpdate(object nextProps, object nextState): boolean` is invoked when a component decides whether any changes warrant an update to the DOM. Implement this as an optimization to compare `this.props` with `nextProps` and `this.state` with `nextState` and return false if React should skip updating.
|
||||
* `componentWillUpdate(object nextProps, object nextState)` is invoked immediately before updating occurs. You cannot call `this.setState()` here.
|
||||
* `componentDidUpdate(object prevProps, object prevState, DOMElement rootNode)` is invoked immediately after updating occurs.
|
||||
|
||||
|
||||
### Unmounting
|
||||
|
||||
* `componentWillUnmount()` is invoked immediately before a component is unmounted and destroyed. Cleanup should go here.
|
||||
|
||||
|
||||
### Mounted Methods
|
||||
|
||||
_Mounted_ composite components also support the following methods:
|
||||
|
||||
* `getDOMNode(): DOMElement` can be invoked on any mounted component in order to obtain a reference to its rendered DOM node.
|
||||
* `forceUpdate()` can be invoked on any mounted component when you know that some deeper aspect of the component's state has changed without using `this.setState()`.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> The `DOMElement rootNode` argument of `componentDidMount()` and
|
||||
> `componentDidUpdate()` is a convenience. The same node can be obtained by
|
||||
> calling `this.getDOMNode()`.
|
||||
|
||||
|
||||
## Browser Support and Polyfills
|
||||
|
||||
At Facebook, we support older browsers, including IE8. We've had polyfills in place for a long time to allow us to write forward-thinking JS. This means we don't have a bunch of hacks scattered throughout our codebase and we can still expect our code to "just work". For example, instead of seeing `+new Date()`, we can just write `Date.now()`. Since the open source React is the same as what we use internally, we've carried over this philosophy of using forward thinking JS.
|
||||
|
||||
In addition to that philosophy, we've also taken the stance that we, as authors of a JS library, should not be shipping polyfills as a part of our library. If every library did this, there's a good chance you'd be sending down the same polyfill multiple times, which could be a sizable chunk of dead code. If your product needs to support older browsers, chances are you're already using something like [es5-shim](https://github.com/kriskowal/es5-shim).
|
||||
|
||||
|
||||
### Polyfills Needed to Support Older Browsers
|
||||
|
||||
These six functions can be polyfilled using `es5-shim.js` from [kriskowal's es5-shim](https://github.com/kriskowal/es5-shim):
|
||||
|
||||
* `Array.isArray`
|
||||
* `Array.prototype.forEach`
|
||||
* `Array.prototype.indexOf`
|
||||
* `Array.prototype.some`
|
||||
* `Date.now`
|
||||
* `Function.prototype.bind`
|
||||
|
||||
Other required polyfills:
|
||||
|
||||
* `Object.create` – Provided by `es5-sham.js` from [kriskowal's es5-shim](https://github.com/kriskowal/es5-shim).
|
||||
* `console.*` – Only needed when using the unminified build. If you need to polyfill this, try [paulmillr's console-polyfill](https://github.com/paulmillr/console-polyfill).
|
||||
135
docs/docs/07.1-more-about-refs.md
Normal file
@@ -0,0 +1,135 @@
|
||||
---
|
||||
id: more-about-refs
|
||||
title: More About Refs
|
||||
layout: docs
|
||||
permalink: more-about-refs.html
|
||||
prev: working-with-the-browser.html
|
||||
next: tooling-integration.html
|
||||
---
|
||||
After returning the structure of your UI from the render method, you may find yourself wanting to "reach out" and invoke methods on component instances returned from render. Often, doing something like this isn't necessary for making data flow through your application, because the Reactive data flow always ensures that the most recent `props` are sent to each child that is output from `render()`. However there are a few cases, where it still might be necessary or beneficial.
|
||||
|
||||
Consider the case when you wish to tell an `<input />` element (that exists within your instances sub-hierarchy) to focus after you update its value to be the empty string, `''`.
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleKeyUp: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
this.setState({userInput: ''}); // Clear the input
|
||||
// We wish to focus the <input /> now!
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click To Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
value={this.state.userInput}
|
||||
onKeyUp={this.handleKeyUp}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
Notice how, in this example, we want to "tell" the input something - something that it cannot infer from its props over time. In this case we want to "tell" it that it should now become focused. However, there are some challenges. What is returned from `render()` is not your actual composition of "child" components, it is merely a *description* of the children at a particular instance in time - a snapshot, if you will.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> Remember, what you return from `render()` is not your *actual* rendered children instances. What you return from `render()` is merely a *description* of the children instances in your component's sub-hierarchy at a particular moment in time.
|
||||
|
||||
|
||||
This means that you should never "hold onto" something that you return from `render()` and then expect it to be anything meaningful.
|
||||
|
||||
```javascript
|
||||
// counterexample: DO NOT DO THIS!
|
||||
render: function() {
|
||||
var myInput = <input />; // I'm going to try to call methods on this
|
||||
this.rememberThisInput = myInput; // input at some point in the future! YAY!
|
||||
return (
|
||||
<div>
|
||||
<div>...</div>
|
||||
{myInput}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
In this counterexample, the `<input />` is merely a *description* of an `<input />`. This description is used to create a *real* **backing instance** for the `<input />`.
|
||||
|
||||
So how do we talk to the *real* backing instance of the input?
|
||||
|
||||
## The ref Attribute
|
||||
|
||||
React supports a very special property that you can attach to any component that is output from `render()`. This special property allows you to refer to the corresponding **backing instance** of anything returned from `render()`. It is always guaranteed to be the proper instance, at any point in time.
|
||||
|
||||
It's as simple as:
|
||||
|
||||
**1.** Assign a `ref` attribute to anything returned from `render` such as:
|
||||
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
|
||||
**2.** In some other code (typically event handler code), access the **backing instance** via `this.refs` as in:
|
||||
|
||||
```javascript
|
||||
this.refs.myInput
|
||||
```
|
||||
|
||||
## Completing the Example
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleKeyUp: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
this.setState({userInput: ''}); // Clear the input
|
||||
this.refs.theInput.getDOMNode().focus(); // Boom! Focused!
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click To Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
ref="theInput"
|
||||
value={this.state.userInput}
|
||||
onKeyUp={this.handleKeyUp}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
In this example, our render function returns a description of an `<input />` instance. But the true instance is accessed via `this.refs.theInput`. As long as a child component with `ref="theInput"` is returned from render, `this.refs.theInput` will access the proper instance. This even works on higher level (non-DOM) components such as `<Typeahead ref="myTypeahead" />`.
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
Refs are a great way to send a message to a particular child instance in a way that would be inconvenient to do via streaming Reactive `props` and `state`. They should, however, not be your go-to abstraction for flowing data through your application. By default, use the Reactive data flow and save `ref`s for use cases that are inherently non-reactive.
|
||||
|
||||
### Benefits:
|
||||
|
||||
- You can define any public method on your component classes (such as a reset method on a Typeahead) and call those public methods through refs (such as `this.refs.myTypeahead.reset()`).
|
||||
- Performing DOM measurements almost always requires reaching out to a "native" component such as `<input />` and accessing its underlying DOM node via `this.refs.myInput.getDOMNode()`. Refs are one of the only practical ways of doing this reliably.
|
||||
- Refs are automatically book-kept for you! If that child is destroyed, its ref is also destroyed for you. No worrying about memory here (unless you do something crazy to retain a reference yourself).
|
||||
|
||||
### Cautions:
|
||||
|
||||
- *Never* access refs inside of any component's render method - or while any component's render method is even running anywhere in the call stack.
|
||||
- If you want to preserve Google Closure Compiler Crushing resilience, make sure to never access as a property what was specified as a string. This means you must access using `this.refs['myRefString']` if your ref was defined as `ref="myRefString"`.
|
||||
- If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where `state` should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use `ref`s to "make things happen" - instead, the data flow will usually accomplish your goal.
|
||||
52
docs/docs/08-tooling-integration.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
id: tooling-integration
|
||||
title: Tooling Integration
|
||||
layout: docs
|
||||
permalink: tooling-integration.html
|
||||
prev: more-about-refs.html
|
||||
next: examples.html
|
||||
---
|
||||
|
||||
Every project uses a different system for building and deploying JavaScript. We've tried to make React as environment-agnostic as possible.
|
||||
|
||||
## React
|
||||
|
||||
### CDN-hosted React
|
||||
|
||||
We provide CDN-hosted versions of React [on our download page](/react/downloads.html). These prebuilt files use the UMD module format. Dropping them in with a simple `<script>` tag will inject a `React` global into your environment. It should also work out-of-the-box in CommonJS and AMD environments.
|
||||
|
||||
|
||||
### Using master
|
||||
|
||||
We have instructions for building from `master` [in our GitHub repository](https://github.com/facebook/react). We build a tree of CommonJS modules under `build/modules` which you can drop into any environment or packaging tool that supports CommonJS.
|
||||
|
||||
## JSX
|
||||
|
||||
### In-browser JSX Transform
|
||||
|
||||
If you like using JSX, we provide an in-browser JSX transformer for development [on our download page](/react/downloads.html). Simply include a `<script type="text/jsx">` tag to engage the JSX transformer. Be sure to include the `/** @jsx React.DOM */` comment as well, otherwise the transformer will not run the transforms.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> The in-browser JSX transformer is fairly large and results in extraneous computation client-side that can be avoided. Do not use it in production — see the next section.
|
||||
|
||||
|
||||
### Productionizing: Precompiled JSX
|
||||
|
||||
If you have [npm](http://npmjs.org/), you can simply run `npm install -g react-tools` to install our command-line `jsx` tool. This tool will translate files that use JSX syntax to plain JavaScript files that can run directly in the browser. It will also watch directories for you and automatically transform files when they are changed; for example: `jsx --watch src/ build/`. Run `jsx --help` for more information on how to use this tool.
|
||||
|
||||
|
||||
### Helpful Open-Source Projects
|
||||
|
||||
The open-source community has built tools that integrate JSX with several build systems.
|
||||
|
||||
* [reactify](https://github.com/andreypopp/reactify) - use JSX with [browserify](http://browserify.org/)
|
||||
* [grunt-react](https://github.com/ericclemmons/grunt-react) - [grunt](http://gruntjs.com/) task for JSX
|
||||
* [require-jsx](https://github.com/seiffert/require-jsx) - use JSX with [require.js](http://requirejs.org/)
|
||||
* [pyReact](https://github.com/facebook/react-python) - use JSX with [Python](http://www.python.org/)
|
||||
* [react-rails](https://github.com/facebook/react-rails) - use JSX with [Ruby on Rails](http://rubyonrails.org/)
|
||||
|
||||
|
||||
## React Page
|
||||
|
||||
To get started on a new project, you can use [react-page](https://github.com/facebook/react-page/), a complete React project creator. It supports both server-side and client-side rendering, source transform and packaging JSX files using CommonJS modules, and instant reload.
|
||||
22
docs/docs/09-examples.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
id: examples
|
||||
title: Examples
|
||||
layout: docs
|
||||
permalink: examples.html
|
||||
prev: tooling-integration.html
|
||||
---
|
||||
|
||||
### Production Apps
|
||||
|
||||
* All of [Instagram.com](http://instagram.com/) is built on React.
|
||||
* Many components on [Facebook.com](http://www.facebook.com/), including the commenting interface, ads creation flows, and page insights.
|
||||
* [Khan Academy](http://khanacademy.org/) is using React for its question editor.
|
||||
|
||||
|
||||
### Sample Code
|
||||
|
||||
* We've included [a step-by-step comment box tutorial](./tutorial.html).
|
||||
* [The React starter kit](/react/downloads.html) includes several examples which you can [view online in our GitHub repository](https://github.com/facebook/react/tree/master/examples/).
|
||||
* [React Page](https://github.com/facebook/react-page) is a simple React project creator to get you up-and-running quickly with React. It supports both server-side and client-side rendering, source transform and packaging JSX files using CommonJS modules, and instant reload.
|
||||
* [React one-hour email](https://github.com/petehunt/react-one-hour-email/commits/master) goes step-by-step from a static HTML mock to an interactive email reader (written in just one hour!)
|
||||
* [Rendr + React app template](https://github.com/petehunt/rendr-react-template/) demonstrates how to use React's server rendering capabilities.
|
||||
96
docs/docs/OUTLINE.md
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
id: OUTLINE
|
||||
title: Goals of the documentation
|
||||
layout: docs
|
||||
prev: 09.1-tutorial.html
|
||||
---
|
||||
- Flow of docs should mimic progression of questions a new user would ask
|
||||
- High information density -- assume the reader is adept at JS
|
||||
- Talk about best practices
|
||||
- JSFiddles for all code samples
|
||||
- Provide background for some of the design decisions
|
||||
- Less words less words less words!
|
||||
|
||||
## Outline
|
||||
|
||||
Motivation / Why React?
|
||||
- Declarative (simple)
|
||||
- Components (separation of concerns)
|
||||
- Give it 5 minutes
|
||||
|
||||
Displaying data
|
||||
- Hello world example
|
||||
- Reactive updates
|
||||
- Components are just functions
|
||||
- JSX syntax (link to separate doc?)
|
||||
- JSX gotchas
|
||||
|
||||
Interactivity and dynamic UIs
|
||||
- Click handler example
|
||||
- Event handlers / synthetic events (link to w3c docs)
|
||||
- Under the hood: autoBind and event delegation (IE8 notes)
|
||||
- React is a state machine
|
||||
- How state works
|
||||
- What components should have state?
|
||||
- What should go in state?
|
||||
- What shouldn't go in state?
|
||||
|
||||
Scaling up: using multiple components
|
||||
- Motivation: separate concerns
|
||||
- Composition example
|
||||
- Ownership (and owner vs. parent)
|
||||
- Children
|
||||
- Data flow (one-way data binding)
|
||||
- A note on performance
|
||||
|
||||
Building effective reusable components
|
||||
- You should build a reusable component library (CSS, testing etc)
|
||||
- Prop validation
|
||||
- Transferring props: a shortcut
|
||||
- Mixins
|
||||
- Testing
|
||||
|
||||
Forms
|
||||
|
||||
Working with the browser
|
||||
- The mock DOM
|
||||
- Refs / getDOMNode()
|
||||
- More about refs
|
||||
- Component lifecycle
|
||||
- Browser support and polyfills
|
||||
|
||||
Working with your environment
|
||||
- CDN-hosted React
|
||||
- Using master
|
||||
- In-browser JSX transform
|
||||
- Productionizing: precompiled JSX
|
||||
- Helpful open-source projects
|
||||
|
||||
Integrating with other UI libraries
|
||||
- Using jQuery plugins
|
||||
- Letting jQuery manage React components
|
||||
- Using with Backbone.View
|
||||
- CoffeeScript
|
||||
- Moving from Handlebars to React: an example
|
||||
|
||||
Server / static rendering
|
||||
- Motivation
|
||||
- Simple example
|
||||
- How does it work? (No DOM)
|
||||
- Rendr + React
|
||||
|
||||
Big ideas
|
||||
- Animation
|
||||
- Bootstrap bindings (responsive grids)
|
||||
- Reactive CSS
|
||||
- Web workers
|
||||
- Native views
|
||||
|
||||
Case studies
|
||||
- Comment box tutorial from scratch
|
||||
- From HTML mock to application: React one-hour email
|
||||
- Jordan's LikeToggler example
|
||||
|
||||
Reference
|
||||
- API
|
||||
- DOM differences
|
||||
@@ -1,119 +0,0 @@
|
||||
---
|
||||
id: docs-advanced-components
|
||||
title: Advanced Components
|
||||
description: How to build advanced composite components.
|
||||
layout: docs
|
||||
prev: event-handling.html
|
||||
next: api.html
|
||||
---
|
||||
|
||||
Composite components extend a `ReactCompositeComponent` base class that provides
|
||||
a very powerful API that makes React flexible and able to easily work with other
|
||||
libraries and frameworks.
|
||||
|
||||
## Lifecycle Methods
|
||||
|
||||
Composite components can optionally implement lifecycle methods that are invoked
|
||||
at various stages in the [component lifecycle](component-lifecycle.html) that
|
||||
each have unique guarantees.
|
||||
|
||||
### Mounting
|
||||
|
||||
- `getInitialState(): object` is invoked before a component is mounted.
|
||||
Stateful components should implement this and return the initial state data.
|
||||
- `componentWillMount()` is invoked immediately before mounting occurs.
|
||||
- `componentDidMount(DOMElement rootNode)` is invoked immediately after
|
||||
mounting occurs. Initialization that requires DOM nodes should go here.
|
||||
|
||||
### Updating
|
||||
|
||||
- `componentWillReceiveProps(object nextProps)` is invoked when a mounted
|
||||
component receives new props. This method should be used to compare
|
||||
`this.props` and `nextProps` to perform state transitions using
|
||||
`this.setState()`.
|
||||
- `shouldComponentUpdate(object nextProps, object nextState): boolean` is
|
||||
invoked when a component decides whether any changes warrant an update to the
|
||||
DOM. Implement this as an optimization to compare `this.props` with
|
||||
`nextProps` and `this.state` with `nextState` and return false if React
|
||||
should skip updating.
|
||||
- `componentWillUpdate(object nextProps, object nextState)` is invoked
|
||||
immediately before updating occurs. You cannot call `this.setState()` here.
|
||||
- `componentDidUpdate(object prevProps, object prevState, DOMElement rootNode)`
|
||||
is invoked immediately after updating occurs.
|
||||
|
||||
### Unmounting
|
||||
|
||||
- `componentWillUnmount()` is invoked immediately before a component is
|
||||
unmounted and destroyed. Cleanup should go here.
|
||||
|
||||
## Mounted Methods
|
||||
|
||||
_Mounted_ composite components also support the following methods:
|
||||
|
||||
- `getDOMNode(): DOMElement` can be invoked on any mounted component in order
|
||||
to obtain a reference to its rendered DOM node.
|
||||
- `forceUpdate()` can be invoked on any mounted component when you know that
|
||||
some deeper aspect of the component's state has changed without using
|
||||
`this.setState()`.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> The `DOMElement rootNode` argument of `componentDidMount()` and
|
||||
> `componentDidUpdate()` is a convenience. The same node can be obtained by
|
||||
> calling `this.getDOMNode()`.
|
||||
|
||||
## Component Refs
|
||||
|
||||
A common use case of event callbacks or the lifecycle methods is to operate on a
|
||||
component returned by `render()`. For example, consider a search component that
|
||||
should auto-focus the input once mounted:
|
||||
|
||||
```javascript
|
||||
var SearchForm = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<form action={this.props.action}>
|
||||
<input type="search" placeholder="Search..." />
|
||||
</form>
|
||||
);
|
||||
},
|
||||
componentDidMount: function(rootNode) {
|
||||
var searchInput = rootNode.firstChild;
|
||||
searchInput.focus();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Although this implementation works, it is fragile because `componentDidMount()`
|
||||
now relies on `render()` returning a particular DOM structure.
|
||||
|
||||
React provides a better way for composite components to reference components
|
||||
that it constructs in its `render()` method through the use of refs. A component
|
||||
can assign a `ref` to any component it constructs. This will create a reference
|
||||
to those components on `this.refs`. For example:
|
||||
|
||||
```javascript{5,10}
|
||||
var SearchForm = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<form action={this.props.action}>
|
||||
<input type="search" placeholder="Search..." ref="searchInput" />
|
||||
</form>
|
||||
);
|
||||
},
|
||||
componentDidMount: function(rootNode) {
|
||||
var searchInput = this.refs.searchInput.getDOMNode();
|
||||
searchInput.focus();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
In this example, `this.refs.searchInput` will reference the `<input>` component
|
||||
and is available in most lifecycle methods and event callbacks. We obtain a
|
||||
reference to the `<input>`'s DOM node using `getDOMNode()`.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> If you want to preserve compatibility with Google Closure Compiler's
|
||||
> property crushing in `ADVANCED_OPTIMIZATIONS` mode, make sure to use string
|
||||
> literals with `this.refs`.
|
||||
150
docs/docs/api.md
@@ -1,150 +0,0 @@
|
||||
---
|
||||
id: docs-api
|
||||
title: React API
|
||||
layout: docs
|
||||
prev: advanced-components.html
|
||||
---
|
||||
|
||||
## React
|
||||
|
||||
`React` is the entry point to the React framework. If you're using one of the prebuilt packages it's available as a global; if you're using CommonJS modules you can `require()` it.
|
||||
|
||||
#### React.DOM
|
||||
|
||||
`React.DOM` provides all of the standard HTML tags needed to build a React app. You generally don't use it directly; instead, just include it as part of the `/** @jsx React.DOM */` docblock.
|
||||
|
||||
#### React.initializeTouchEvents
|
||||
|
||||
```javascript
|
||||
initializeTouchEvents(boolean shouldUseTouch)
|
||||
```
|
||||
|
||||
Configure React's event system to handle touch events on mobile devices.
|
||||
|
||||
#### React.autoBind
|
||||
|
||||
```javascript
|
||||
function autoBind(function method)
|
||||
```
|
||||
|
||||
Marks the provided function to be automatically bound to each React component instance created. This allows React components to define automatically bound methods and ensure that when called they will always reference their current instance.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
React.createClass({
|
||||
click: React.autoBind(function(evt) {
|
||||
this.setState({jumping: true});
|
||||
}),
|
||||
render: function() {
|
||||
// Look: no bind!
|
||||
return <a onClick={this.click}>Jump</a>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### React.createClass
|
||||
|
||||
```javascript
|
||||
function createClass(object specification)
|
||||
```
|
||||
|
||||
Creates a component given a specification. A component implements a `render` method which returns a single child. That child may have an arbitrarily deep child structure. One thing that makes components different than a standard prototypal classes is that you don't need to call new on them. They are convenience wrappers that construct backing instances (via new) for you.
|
||||
|
||||
#### React.renderComponent
|
||||
|
||||
```javascript
|
||||
ReactComponent renderComponent(ReactComponent container, DOMElement mountPoint)
|
||||
```
|
||||
|
||||
Renders a React component into the DOM in the supplied `container`.
|
||||
|
||||
If the React component was previously rendered into `container`, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React component.
|
||||
|
||||
## AbstractEvent
|
||||
|
||||
Your event handlers will be passed instances of `AbstractEvent`, a cross-browser wrapper around the browser's native event. It has the same interface as the browser's native event (such as `stopPropagation()` and `preventDefault()`) except they work exactly the same across all browsers.
|
||||
|
||||
If you find that you need the underlying browser event for some reason, simply use the `nativeEvent` attribute to get it.
|
||||
|
||||
## ReactComponent
|
||||
|
||||
Component classses created by `createClass()` return instances of `ReactComponent` when called. Most of the time when you're using React you're either creating or consuming `ReactComponent`s.
|
||||
|
||||
#### getDOMNode
|
||||
|
||||
```javascript
|
||||
DOMElement getDOMNode()
|
||||
```
|
||||
|
||||
If this component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements.
|
||||
|
||||
#### setProps
|
||||
|
||||
```javascript
|
||||
setProps(object nextProps)
|
||||
```
|
||||
|
||||
When you're integrating with an external JavaScript application you may want to signal a change to a React component rendered with `renderComponent()`. Simply call `setProps()` to change its properties and trigger a re-render.
|
||||
|
||||
**Note:** This method can only be called on a root-level component. That is, it's only available on the component passed directly to `renderComponent()` and none of its children. If you're inclined to use `setProps()` on a child component, instead take advantage of reactive updates and pass the new prop to the child component when it's created in `render()`.
|
||||
|
||||
#### replaceProps
|
||||
|
||||
```javascript
|
||||
replaceProps(object nextProps)
|
||||
```
|
||||
|
||||
Like `setProps()` but deletes any pre-existing props that are not in nextProps.
|
||||
|
||||
#### transferPropsTo
|
||||
|
||||
```javascript
|
||||
ReactComponent transferPropsTo(ReactComponent targetComponent)
|
||||
```
|
||||
|
||||
Transfer properties from this component to a target component that have not already been set on the target component. This is usually used to pass down properties to the returned root component. `targetComponent`, now updated with some new props is returned as a convenience.
|
||||
|
||||
#### setState
|
||||
|
||||
```javascript
|
||||
setState(object nextState)
|
||||
```
|
||||
|
||||
Merges nextState with the current state. This is the primary method you use to trigger UI updates from event handlers and server request callbacks.
|
||||
|
||||
**Note:** *NEVER* mutate `this.state` directly. As calling `setState()` afterwards may replace the mutation you made. Treat `this.state` as if it were immutable.
|
||||
|
||||
**Note:** `setState()` does not immediately mutate `this.state` but creates a pending state transition. Accessing `this.state` after calling this method can potentially return the existing value.
|
||||
|
||||
#### replaceState
|
||||
|
||||
```javascript
|
||||
replaceState(object nextState)
|
||||
```
|
||||
|
||||
Like `setState()` but deletes any pre-existing state keys that are not in nextState.
|
||||
|
||||
#### forceUpdate()
|
||||
|
||||
```javascript
|
||||
forceUpdate()
|
||||
```
|
||||
|
||||
If your `render()` method reads from something other than `this.props` or `this.state` you'll need to tell React when it needs to re-run `render()`. Use `forceUpdate()` to cause React to automatically re-render. This will cause `render()` to be called on the component and all of its children but React will only update the DOM if the markup changes.
|
||||
|
||||
Normally you should try to avoid all uses of `forceUpdate()` and only read from `this.props` and `this.state` in `render()`. This makes your application much simpler and more efficient.
|
||||
|
||||
```javascript
|
||||
object getInitialState()
|
||||
componentWillMount()
|
||||
componentDidMount(DOMElement domNode)
|
||||
componentWillReceiveProps(object nextProps)
|
||||
boolean shouldComponentUpdate(object nextProps, object nextState)
|
||||
componentWillUpdate(object nextProps, object nextState)
|
||||
ReactComponent render()
|
||||
componentDidUpdate(object prevProps, object prevState, DOMElement domNode)
|
||||
componentWillUnmount()
|
||||
```
|
||||
|
||||
See the [advanced components](advanced-components.html) documentation for more details on these lifecycle methods.
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
id: docs-common-questions
|
||||
title: Common Questions
|
||||
layout: docs
|
||||
prev: tutorial.html
|
||||
next: syntax.html
|
||||
---
|
||||
### What browsers does React support?
|
||||
|
||||
React supports the latest two Chrome, Firefox, Safari, and Internet Explorer versions. React can work with Internet Explorer 8 with polyfills.
|
||||
|
||||
### How do I get React to support Internet Explorer 8?
|
||||
|
||||
React requires ES5 JavaScript shims to run in Internet Explorer 8. Include the [ES5 Shims](https://github.com/kriskowal/es5-shim) to implement these shims.
|
||||
|
||||
### Who uses React?
|
||||
|
||||
The [Instagram](http://instagram.com/) website is built entirely in React. The [Facebook](https://www.facebook.com/) website is also increasingly using React, including the common commenting plugin across the site.
|
||||
|
||||
### Can I integrate with other JavaScript libraries?
|
||||
|
||||
Absolutely! In fact, we encourage it! See [our GitHub repo](http://github.com/facebook/react/) for a [TodoMVC example using Backbone](https://github.com/facebook/react/tree/master/examples/todomvc-backbone) and a [jQuery + Bootstrap modal demo](https://github.com/facebook/react/tree/master/examples/jquery-bootstrap).
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
id: docs-component-basics
|
||||
title: Component Basics
|
||||
description: What are components?
|
||||
layout: docs
|
||||
next: component-data.html
|
||||
prev: syntax.html
|
||||
---
|
||||
|
||||
_Components_ are the basic units of composition in React. Components encapsulate
|
||||
the logic necessary to take input parameters and render markup. Components can
|
||||
be rendered into an existing DOM element on the page by using
|
||||
`React.renderComponent`:
|
||||
|
||||
```javascript
|
||||
// Replaces everything in `document.body` with <div>Hello, world!</div>;
|
||||
React.renderComponent(<div>Hello, world!</div>, document.body);
|
||||
```
|
||||
|
||||
Keep in mind that `<div>` is **not** a DOM element! Keep reading...
|
||||
|
||||
## Types of Components
|
||||
|
||||
There are two types of components:
|
||||
|
||||
- **Composite Components**
|
||||
- **DOM Components**
|
||||
|
||||
### Composite Components <small>such as `TodoApp` and `Typeahead`.</small>
|
||||
|
||||
The majority of your React code will be implementing composite components.
|
||||
|
||||
Composite components are higher-level components with custom rendering logic
|
||||
that may compose other composite components or DOM components.
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
var LinkButton = React.createClass({
|
||||
render: function() {
|
||||
return <a className="btn" />;
|
||||
}
|
||||
});
|
||||
|
||||
var myButton = <LinkButton />;
|
||||
```
|
||||
|
||||
This example defines a `LinkButton` component class using `React.createClass()`,
|
||||
and its `render()` method composes the `<a>` DOM component.
|
||||
|
||||
### DOM Components <small>such as `div` and `span`.</small>
|
||||
|
||||
DOM components are the set of classes that correspond to browser DOM elements.
|
||||
They are defined in `React.DOM` and can be brought "into scope" by setting
|
||||
`@jsx React.DOM` in the docblock. See [JSX Syntax](syntax.html) for more
|
||||
details.
|
||||
|
||||
Although `React.DOM` components look like browser DOM elements, they differ in a
|
||||
few ways:
|
||||
|
||||
- All property names, including event handlers, are camelCased.
|
||||
- JavaScript identifiers should be used, namely `className` and `htmlFor`.
|
||||
- The `style` prop expects an object instead of a string. The object should map
|
||||
camelCased style properties to values, e.g. `{backgroundColor: '#fff'}`.
|
||||
|
||||
Here is an example of a React link styled as a button with a click handler:
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
var handleClick = function() {alert('Clicked!');};
|
||||
var inlineStyle = {textDecoration: 'none'};
|
||||
|
||||
var myLink = <a className="btn" onClick={handleClick} style={inlineStyle} />;
|
||||
```
|
||||
@@ -1,145 +0,0 @@
|
||||
---
|
||||
id: docs-component-data
|
||||
title: Component Data
|
||||
description: How is data passed into a component?
|
||||
layout: docs
|
||||
prev: component-basics.html
|
||||
next: component-lifecycle.html
|
||||
---
|
||||
|
||||
## Props
|
||||
|
||||
Components use data to determine what should be rendered. For example:
|
||||
|
||||
```javascript
|
||||
var LikeLink = React.createClass({
|
||||
render: function() {
|
||||
var text = this.props.liked ? 'Liked' : 'Like';
|
||||
return <a>{text}</a>;
|
||||
}
|
||||
});
|
||||
var myLikeLink = <LikeLink liked={false} />;
|
||||
```
|
||||
|
||||
In this example, `LikeLink` takes `liked` as boolean data. This type of data
|
||||
that is passed in is called a "prop". Examples of props on DOM components
|
||||
include `className` and `onClick`.
|
||||
|
||||
Whenever a component's props change, its `render()` function will be
|
||||
re-evaluated and the DOM will be updated. React will ensure that the DOM is
|
||||
always kept up-to-date.
|
||||
|
||||
## State
|
||||
|
||||
Let's build a small `LikeApp` application that makes use of the `<LikeLink>`
|
||||
component from above. It should start off unliked and we should be able to like
|
||||
it by clicking the link:
|
||||
|
||||
```javascript
|
||||
var LikeApp = React.createClass({
|
||||
render: function() {
|
||||
var isClicked = false;
|
||||
return <LikeLink liked={isClicked} onClick={this.handleClick.bind(this)} />;
|
||||
},
|
||||
handleClick: function() {
|
||||
// Somehow update `isClicked`.
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
This renders a `<LikeLink>` with a click listener. However, it is not clear how
|
||||
`handleClick` should update `isClicked` to true. `LikeApp` needs a way to store
|
||||
**state** about whether or not it has been clicked.
|
||||
|
||||
### State vs. Props
|
||||
|
||||
State is data that is managed _internally_ by a composite component. Like props,
|
||||
the `render()` function will be re-evaluated whenever state changes. Props and
|
||||
state differ in that:
|
||||
|
||||
- Props are passed in from the creator.
|
||||
- State is private to and managed by the component.
|
||||
|
||||
### Managing State
|
||||
|
||||
Let's update our `LikeApp` component using state:
|
||||
|
||||
```javascript{2-4,6,10}
|
||||
var LikeApp = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {isClicked: false};
|
||||
},
|
||||
render: function() {
|
||||
var isClicked = this.state.isClicked;
|
||||
return <LikeLink liked={isClicked} onClick={this.handleClick.bind(this)} />;
|
||||
},
|
||||
handleClick: function() {
|
||||
this.setState({isClicked: true});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
There's a lot going on here, so let's work our way from top to bottom:
|
||||
|
||||
- `getInitialState()` describes what state data looks like when the component
|
||||
is created.
|
||||
- In `render()`, state data can be accessed via `this.state`.
|
||||
- When the link is clicked, we update state using `setState()`.
|
||||
|
||||
Now when we click the link, the `<LikeLink>` will get updated, right? Wrong.
|
||||
|
||||
## Transferring Props
|
||||
|
||||
If you have been following carefully, you may have noticed that although we pass
|
||||
a click handler into `<LikeLink>` as a prop, `LikeLink` does not do anything
|
||||
with `this.props.onClick`! Let's fix that.
|
||||
|
||||
```javascript{4}
|
||||
var LikeLink = React.createClass({
|
||||
render: function() {
|
||||
var text = this.props.liked ? 'Liked' : 'Like';
|
||||
return <a onClick={this.props.onClick}>{text}</a>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Although this works, realize that this would quickly become tedious if we wanted
|
||||
to also transfer `href`, `title`, `target`, and other events from `this` to the
|
||||
rendered `<a>`. React provides a convenience method, `transferPropsTo()`, for
|
||||
transferring props:
|
||||
|
||||
```javascript{4}
|
||||
var LikeLink = React.createClass({
|
||||
render: function() {
|
||||
var text = this.props.liked ? 'Liked' : 'Like';
|
||||
return this.transferPropsTo(<a>{text}</a>);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
This will transfer all props from `this` to the specified component (including
|
||||
`onClick`).
|
||||
|
||||
## Summary
|
||||
|
||||
Now we are done. `LikeApp` renders an unliked link which, when clicked, will:
|
||||
|
||||
1. Update the internal state of `LikeApp`.
|
||||
2. Change the props passed into `LikeLink`.
|
||||
3. Change the return value of `render()`.
|
||||
4. Trigger an update to the DOM.
|
||||
|
||||
It's worth noting that React will handle new return values of `render()` by
|
||||
making the mininal set of mutations necessary to bring the DOM up-to-date. In
|
||||
this case, only the `textContent` of the rendered link will be mutated.
|
||||
|
||||
In summary:
|
||||
|
||||
- Props are passed in whereas state is managed internally by a component.
|
||||
- Never mutate `this.props` or `this.state`. You should pass props into other
|
||||
components and mutate state using `setState()`.
|
||||
- State is private. Never read `state` or call `setState()` on
|
||||
anything but `this`.
|
||||
- Whenever props or state changes, `render()` will be re-evaluated and the DOM
|
||||
updated. Also, `render()` should not depend on anything besides `this.props`
|
||||
and `this.state`.
|
||||
@@ -1,85 +0,0 @@
|
||||
---
|
||||
id: docs-component-lifecycle
|
||||
title: Component Lifecycle
|
||||
description: What happens when I render a React component?
|
||||
layout: docs
|
||||
prev: component-data.html
|
||||
next: event-handling.html
|
||||
---
|
||||
|
||||
## Mounting
|
||||
|
||||
[We have previously seen](component-basics.html) how to render components into
|
||||
existing DOM elements on the page:
|
||||
|
||||
```javascript
|
||||
React.renderComponent(<div>Hello, world!</div>, document.body);
|
||||
```
|
||||
|
||||
In this one simple line, we have accomplished the following:
|
||||
|
||||
- A `<div>` (defined by `React.DOM.div`) component is instantiated.
|
||||
- The component is **mounted** into `document.body`.
|
||||
|
||||
**Mounting** is the process of initializing a React component by creating its
|
||||
DOM nodes and inserting the them into a supplied container node.
|
||||
|
||||
At this point, the entire page consists of a single `<div>` with "Hello,
|
||||
world!".
|
||||
|
||||
## Updating
|
||||
|
||||
Let's add a second call to `React.renderComponent()` after three
|
||||
seconds:
|
||||
|
||||
```javascript{2-4}
|
||||
React.renderComponent(<div>Hello, world!</div>, document.body);
|
||||
setTimeout(function() {
|
||||
React.renderComponent(<div>Goodbye, world.</div>, document.body);
|
||||
}, 3000);
|
||||
```
|
||||
|
||||
The second call to `React.renderComponent()` will trigger the following:
|
||||
|
||||
- The `<div>` component will check the new props to see if anything changed.
|
||||
- The set of changes are used to **update** the DOM node as necessary.
|
||||
|
||||
**Updating** is the process of mutating the rendered DOM nodes and occurs
|
||||
whenever either props or state has changed. This ensures that the rendered DOM
|
||||
is consistent with the data.
|
||||
|
||||
## Unmounting
|
||||
|
||||
Let's add one final call to `React.renderComponent()` after another three
|
||||
seconds:
|
||||
|
||||
```javascript{5-7}
|
||||
React.renderComponent(<div>Hello, world!</div>, document.body);
|
||||
setTimeout(function() {
|
||||
React.renderComponent(<div>Goodbye, world.</div>, document.body);
|
||||
}, 3000);
|
||||
setTimeout(function() {
|
||||
React.renderComponent(<img src="/images/fin.png" />, document.body);
|
||||
}, 6000);
|
||||
```
|
||||
|
||||
The third call to `React.renderComponent()` will trigger the following:
|
||||
|
||||
- An `<img>` (defined by `React.DOM.img`) component is instantiated.
|
||||
- React will compare the `<div>` component with the `<img>` component.
|
||||
- Since the component class is different, the `<div>` component will be
|
||||
**unmounted**.
|
||||
- The `<img>` component will then be mounted into `document.body`.
|
||||
|
||||
**Unmounting** is the process of releasing resources that have been allocated by
|
||||
a component. This allows user interfaces built with React to live long without
|
||||
memory leaks.
|
||||
|
||||
Components can also be unmounted using
|
||||
`React.unmountAndReleaseReactRootNode()`:
|
||||
|
||||
```javascript
|
||||
React.unmountAndReleaseReactRootNode(document.body);
|
||||
```
|
||||
|
||||
This will unmount any components mounted immediately within `document.body`.
|
||||
@@ -1,224 +0,0 @@
|
||||
---
|
||||
id: docs-event-handling
|
||||
title: Event Handling
|
||||
description: How do events work with React components?
|
||||
layout: docs
|
||||
prev: component-lifecycle.html
|
||||
next: advanced-components.html
|
||||
---
|
||||
|
||||
Events in React work the way they do with HTML, except the event names are
|
||||
camelCased.
|
||||
|
||||
```javascript
|
||||
var Clicker = React.createClass({
|
||||
render: function() {
|
||||
return <span onClick={this.handleClick}>Click me!</span>;
|
||||
},
|
||||
handleClick: function(event) {
|
||||
alert('You clicked me!');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
When `<Clicker>` is clicked, the `handleClick()` function will get fired. Under
|
||||
the hood, React uses top-level event delegation to achieve high performance.
|
||||
|
||||
## Automatically Binding Callbacks
|
||||
|
||||
Just like any callback in JavaScript, if you want to refer to the component as
|
||||
`this` from the callback, you need to bind the callback to the component:
|
||||
|
||||
```javascript{3}
|
||||
var Clicker = React.createClass({
|
||||
render: function() {
|
||||
var handleClick = this.handleClick.bind(this);
|
||||
return <span onClick={handleClick}>Click me!</span>;
|
||||
},
|
||||
handleClick: function(event) {
|
||||
alert(this.ALERT_MESSAGE);
|
||||
},
|
||||
ALERT_MESSAGE: 'You clicked me!'
|
||||
});
|
||||
```
|
||||
|
||||
React provides a convenient and _efficient_ way to bind methods using
|
||||
`React.autoBind()`:
|
||||
|
||||
```javascript{3,5-7}
|
||||
var Clicker = React.createClass({
|
||||
render: function() {
|
||||
return <span onClick={this.handleClick}>Click me!</span>;
|
||||
},
|
||||
handleClick: React.autoBind(function(event) {
|
||||
alert(this.ALERT_MESSAGE);
|
||||
}),
|
||||
ALERT_MESSAGE: 'You clicked me!'
|
||||
});
|
||||
```
|
||||
|
||||
> Note:
|
||||
>
|
||||
> Binding a function allocates memory to create a new bound function. Since
|
||||
> `render()` may be invoked many times, it is a bad place to bind functions.
|
||||
> `React.autoBind()` sidesteps this issue by only binding once at instantiation
|
||||
> time.
|
||||
|
||||
## DOM Events
|
||||
|
||||
React uses [top-level event delegation](http://davidwalsh.name/event-delegate)
|
||||
to achieve high performance when implementing DOM events. For each type of DOM
|
||||
event, React adds a single top-level listener and determines which event
|
||||
handlers to execute by simulating event capturing and bubbling.
|
||||
|
||||
DOM event handlers are called with a normalized `AbstractEvent` object that has
|
||||
cross-browser compatible implementations of `stopPropagation` and
|
||||
`preventDefault()`. If you need access to the raw browser event, you can use the
|
||||
`nativeEvent` property.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> The `AbstractEvent` object is JSON serializable so that React applications can
|
||||
> be executed inside web workers.
|
||||
|
||||
### Touch Events
|
||||
|
||||
If you want to use touch events, you must configure React's event system to
|
||||
initialize them:
|
||||
|
||||
```javascript
|
||||
// Invoke before calling `React.renderComponent()`.
|
||||
React.initializeTouchEvents(true);
|
||||
```
|
||||
|
||||
## Custom Events
|
||||
|
||||
Notice that event listeners are attached by simply passing them into components
|
||||
as props. For DOM components, events are handled using top-level event
|
||||
delegation. For composite components, event handling is up to the component's
|
||||
implementation.
|
||||
|
||||
Here is an example of a toggle link that fires a custom `onToggle` event:
|
||||
|
||||
```javascript
|
||||
var ToggleLink = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {isEnabled: false};
|
||||
},
|
||||
render: function() {
|
||||
return <a onClick={this.handleClick}>Toggle</a>;
|
||||
},
|
||||
handleClick: React.autoBind(function() {
|
||||
var willEnable = !this.state.isEnabled;
|
||||
if (this.props.onToggle) {
|
||||
this.props.onToggle(willEnable)
|
||||
}
|
||||
this.setState({isEnabled: willEnable});
|
||||
})
|
||||
});
|
||||
|
||||
var handleToggle = function(enabled) {
|
||||
alert(enabled ? 'Enabled.' : 'Disabled.');
|
||||
};
|
||||
var myToggleLink = <ToggleLink onToggle={handleToggle} />;
|
||||
```
|
||||
|
||||
### Common Patterns
|
||||
|
||||
With React your event handlers should be quite small. Large event handlers may
|
||||
be symptomatic of code that should be moved into helpers or into `render()`.
|
||||
Here are some common usage patterns for event handlers.
|
||||
|
||||
#### Updating State
|
||||
|
||||
The most common thing to do in response to a user action is to call
|
||||
`this.setState()` to update the component's state, which will in turn trigger
|
||||
an update to the rendered component.
|
||||
|
||||
#### Server Requests
|
||||
|
||||
Many event handlers will issue a server request to read or write some data in
|
||||
response to an event. The response handler for the request will often call
|
||||
`this.setState()`.
|
||||
|
||||
#### Invoke a Callback
|
||||
|
||||
Your component will often be a small, reusable building block that does not know
|
||||
how to respond to a user action. In these situations, we delegate the
|
||||
responsibility to the owner by exposing a handler on `this.props`. This is what
|
||||
the `ToggleLink` example above is doing.
|
||||
|
||||
#### Inter-component Communication
|
||||
|
||||
A common scenario involves communicating to **Component A** that a user action
|
||||
has occurred on **Component B**. To solve this problem, a common parent to
|
||||
both components should listen for the event on **Component B**, update its
|
||||
internal state, and pass that data into **Component A**.
|
||||
|
||||
For example, say we have two components: **Clicker**, a component that fires an
|
||||
`onCountChange` custom event, and **ClickCountLabel**, a component that displays
|
||||
the number of clicks that have happened:
|
||||
|
||||
```javascript
|
||||
var Clicker = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {count: 0};
|
||||
},
|
||||
render: function() {
|
||||
return <span onClick={this.handleClick}>Click me!</span>;
|
||||
},
|
||||
handleClick: React.autoBind(function() {
|
||||
this.setState({count: this.state.count + 1});
|
||||
if (this.props.onCountChange) {
|
||||
this.props.onCountChange(this.state.count);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
var ClickCountLabel = React.createClass({
|
||||
render: function() {
|
||||
return <p>You have clicked <strong>{this.props.count}</strong> times.</p>;
|
||||
}
|
||||
});
|
||||
|
||||
var ClickApp = React.createClass({
|
||||
render: function() {
|
||||
var count = 0;
|
||||
return (
|
||||
<div>
|
||||
<Clicker onCountChange={this.handleCountChange} />
|
||||
<ClickCountLabel count={count} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleCountChange: React.autoBind(function(count) {
|
||||
// Somehow update `count`.
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
In order to communicate the click count from `Clicker` to `ClickCountLabel`, we
|
||||
modify `ClickApp` to maintain state that will be passed into `ClickCountLabel`:
|
||||
|
||||
```javascript{2-4,6,15}
|
||||
var ClickApp = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {count: 0};
|
||||
},
|
||||
render: function() {
|
||||
var count = this.state.count;
|
||||
return (
|
||||
<div>
|
||||
<Clicker onCountChange={this.handleCountChange} />
|
||||
<ClickCountLabel count={count} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleCountChange: React.autoBind(function(count) {
|
||||
this.setState({count: count});
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
Now when `Clicker` fires the `onCountChange` event, the `ClickCountLabel` will
|
||||
get updated!
|
||||
@@ -1,9 +1,19 @@
|
||||
---
|
||||
id: docs-getting-started
|
||||
id: getting-started
|
||||
title: Getting Started
|
||||
layout: docs
|
||||
next: tutorial.html
|
||||
---
|
||||
|
||||
## JSFiddle
|
||||
|
||||
The easiest way to start hacking on React is using the following JSFiddle Hello Worlds
|
||||
|
||||
* **[React JSFiddle](http://jsfiddle.net/vjeux/kb3gN/)**
|
||||
* [React JSFiddle without JSX](http://jsfiddle.net/vjeux/VkebS/)
|
||||
|
||||
## Starter Kit
|
||||
|
||||
Download the starter kit to get started.
|
||||
|
||||
<div class="buttons-unit downloads">
|
||||
@@ -12,8 +22,6 @@ Download the starter kit to get started.
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Hello, world!
|
||||
|
||||
In the root directory of the starter kit, create a `helloworld.html` with the following contents.
|
||||
|
||||
```html
|
||||
@@ -36,7 +44,7 @@ In the root directory of the starter kit, create a `helloworld.html` with the fo
|
||||
</html>
|
||||
```
|
||||
|
||||
The XML syntax inside of JavaScript is called JSX; check out the [JSX syntax](syntax.html) to learn more about it. In order to translate it to vanilla JavaScript we use `<script type="text/jsx">` and include `JSXTransformer.js` to actually perform the transformation in the browser.
|
||||
The XML syntax inside of JavaScript is called JSX; check out the [JSX syntax](jsx-in-depth.html) to learn more about it. In order to translate it to vanilla JavaScript we use `<script type="text/jsx">` and include `JSXTransformer.js` to actually perform the transformation in the browser.
|
||||
|
||||
### Separate File
|
||||
|
||||
@@ -76,10 +84,14 @@ The file `build/helloworld.js` is autogenerated whenever you make a change.
|
||||
/** @jsx React.DOM */
|
||||
React.renderComponent(
|
||||
React.DOM.h1(null, 'Hello, world!'),
|
||||
document.getElementyById('example')
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
> Note:
|
||||
>
|
||||
> The comment parser is very strict right now, in order for it to pick up the `@jsx` modifier, two conditions are required. The `@jsx` comment block must be the first comment on the file. The comment must start with `/**` (`/*` and `//` will not work). If the parser can't find the `@jsx` comment, it will output the file without transforming it.
|
||||
|
||||
Update your HTML file as below:
|
||||
|
||||
```html{6,10}
|
||||
|
||||
4
docs/docs/index.html
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
destination: getting-started.html
|
||||
---
|
||||
73
docs/docs/ref-01-top-level-api.md
Normal file
@@ -0,0 +1,73 @@
|
||||
---
|
||||
id: top-level-api
|
||||
title: Top-Level API
|
||||
layout: docs
|
||||
permalink: top-level-api.html
|
||||
next: component-api.html
|
||||
---
|
||||
|
||||
## React
|
||||
|
||||
`React` is the entry point to the React framework. If you're using one of the prebuilt packages it's available as a global; if you're using CommonJS modules you can `require()` it.
|
||||
|
||||
|
||||
### React.DOM
|
||||
|
||||
`React.DOM` provides all of the standard HTML tags needed to build a React app. You generally don't use it directly; instead, just include it as part of the `/** @jsx React.DOM */` docblock.
|
||||
|
||||
|
||||
### React.initializeTouchEvents
|
||||
|
||||
```javascript
|
||||
initializeTouchEvents(boolean shouldUseTouch)
|
||||
```
|
||||
|
||||
Configure React's event system to handle touch events on mobile devices.
|
||||
|
||||
|
||||
### React.createClass
|
||||
|
||||
```javascript
|
||||
function createClass(object specification)
|
||||
```
|
||||
|
||||
Creates a component given a specification. A component implements a `render` method which returns **one single** child. That child may have an arbitrarily deep child structure. One thing that makes components different than standard prototypal classes is that you don't need to call new on them. They are convenience wrappers that construct backing instances (via new) for you.
|
||||
|
||||
For more information about the specification object, see [Component Specs and Lifecycle](component-specs.html).
|
||||
|
||||
|
||||
### React.renderComponent
|
||||
|
||||
```javascript
|
||||
ReactComponent renderComponent(
|
||||
ReactComponent component,
|
||||
DOMElement container,
|
||||
[function callback]
|
||||
)
|
||||
```
|
||||
|
||||
Renders a React component into the DOM in the supplied `container`.
|
||||
|
||||
If the React component was previously rendered into `container`, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React component.
|
||||
|
||||
If the optional callback is provided, it will be executed after the component is rendered or updated.
|
||||
|
||||
|
||||
### React.unmountAndReleaseReactRootNode
|
||||
|
||||
```javascript
|
||||
unmountAndReleaseReactRootNode(DOMElement container)
|
||||
```
|
||||
|
||||
Remove a mounted React component from the DOM and clean up its event handlers and state.
|
||||
|
||||
|
||||
### React.renderComponentToString
|
||||
|
||||
```javascript
|
||||
renderComponentToString(ReactComponent component, function callback)
|
||||
```
|
||||
|
||||
Render a component to its initial HTML. This should only be used on the server. React will call `callback` with an HTML string when the markup is ready. You can use this method to can generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes.
|
||||
|
||||
If you call `React.renderComponent()` on a node that already has this server-rendered markup, React will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.
|
||||
109
docs/docs/ref-02-component-api.md
Normal file
@@ -0,0 +1,109 @@
|
||||
---
|
||||
id: component-api
|
||||
title: Component API
|
||||
layout: docs
|
||||
permalink: component-api.html
|
||||
prev: top-level-api.html
|
||||
next: component-specs.html
|
||||
---
|
||||
|
||||
## ReactComponent
|
||||
|
||||
Component classses created by `createClass()` return instances of `ReactComponent` when called. Most of the time when you're using React you're either creating or consuming these component objects.
|
||||
|
||||
|
||||
### getDOMNode
|
||||
|
||||
```javascript
|
||||
DOMElement getDOMNode()
|
||||
```
|
||||
|
||||
If this component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements.
|
||||
|
||||
|
||||
### setProps
|
||||
|
||||
```javascript
|
||||
setProps(object nextProps)
|
||||
```
|
||||
|
||||
When you're integrating with an external JavaScript application you may want to signal a change to a React component rendered with `renderComponent()`. Simply call `setProps()` to change its properties and trigger a re-render.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> This method can only be called on a root-level component. That is, it's only available on the component passed directly to `renderComponent()` and none of its children. If you're inclined to use `setProps()` on a child component, instead take advantage of reactive updates and pass the new prop to the child component when it's created in `render()`.
|
||||
|
||||
|
||||
### replaceProps
|
||||
|
||||
```javascript
|
||||
replaceProps(object nextProps)
|
||||
```
|
||||
|
||||
Like `setProps()` but deletes any pre-existing props instead of merging the two objects.
|
||||
|
||||
|
||||
### transferPropsTo
|
||||
|
||||
```javascript
|
||||
ReactComponent transferPropsTo(ReactComponent targetComponent)
|
||||
```
|
||||
|
||||
Transfer properties from this component to a target component that have not already been set on the target component. After the props are updated, `targetComponent` is returned as a convenience. This function is useful when creating simple HTML-like components:
|
||||
|
||||
```javascript
|
||||
var Avatar = React.createClass({
|
||||
render: function() {
|
||||
return this.transferPropsTo(
|
||||
<img src={"/avatars/" + this.props.userId + ".png"} userId={null} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// <AvatarImage userId={17} width={200} height={200} />
|
||||
```
|
||||
|
||||
Properties that are specified directly on the target component instance (such as `src` and `userId` in the above example) will not be overwritten by `transferPropsTo`.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> Use `transferPropsTo` with caution; it encourages tight coupling and makes it easy to accidentally introduce implicit dependencies between components. When in doubt, it's safer to explicitly copy the properties that you need onto the child component.
|
||||
|
||||
|
||||
### setState
|
||||
|
||||
```javascript
|
||||
setState(object nextState[, function callback])
|
||||
```
|
||||
|
||||
Merges nextState with the current state. This is the primary method you use to trigger UI updates from event handlers and server request callbacks. In addition, you can supply an optional callback function that is executed once `setState` is completed.
|
||||
|
||||
> Notes:
|
||||
>
|
||||
> *NEVER* mutate `this.state` directly, as calling `setState()` afterwards may replace the mutation you made. Treat `this.state` as if it were immutable.
|
||||
>
|
||||
> `setState()` does not immediately mutate `this.state` but creates a pending state transition. Accessing `this.state` after calling this method can potentially return the existing value.
|
||||
>
|
||||
> There is no guarantee of synchronous operation of calls to `setState` and calls may be batched for performance gains.
|
||||
|
||||
|
||||
### replaceState
|
||||
|
||||
```javascript
|
||||
replaceState(object nextState[, function callback])
|
||||
```
|
||||
|
||||
Like `setState()` but deletes any pre-existing state keys that are not in nextState.
|
||||
|
||||
|
||||
### forceUpdate()
|
||||
|
||||
```javascript
|
||||
forceUpdate([function callback])
|
||||
```
|
||||
|
||||
If your `render()` method reads from something other than `this.props` or `this.state`, you'll need to tell React when it needs to re-run `render()` by calling `forceUpdate()`. You'll also need to call `forceUpdate()` if you mutate `this.state` directly.
|
||||
|
||||
Calling `forceUpdate()` will cause `render()` to be called on the component and its children, but React will still only update the DOM if the markup changes.
|
||||
|
||||
Normally you should try to avoid all uses of `forceUpdate()` and only read from `this.props` and `this.state` in `render()`. This makes your application much simpler and more efficient.
|
||||
176
docs/docs/ref-03-component-specs.md
Normal file
@@ -0,0 +1,176 @@
|
||||
---
|
||||
id: component-specs
|
||||
title: Component Specs and Lifecycle
|
||||
layout: docs
|
||||
permalink: component-specs.html
|
||||
prev: component-api.html
|
||||
next: tags-and-attributes.html
|
||||
---
|
||||
|
||||
## Component Specifications
|
||||
|
||||
When creating a component class by invoking `React.createClass()`, you should provide a specification object that contains a `render` method and can optionally contain other lifecycle methods described here.
|
||||
|
||||
|
||||
### render
|
||||
|
||||
```javascript
|
||||
ReactComponent render()
|
||||
```
|
||||
|
||||
The `render()` method is required.
|
||||
|
||||
When called, it should examine `this.props` and `this.state` and return a single child component. This child component can be either a native DOM component (such as `<div>`) or another composite component that you've defined yourself.
|
||||
|
||||
The `render()` function should be *pure*, meaning that it does not modify component state, it returns the same result each time it's invoked, and it does not read from or write to the DOM or otherwise interact with the browser (e.g., by using `setTimeout`). If you need to interact with the browser, perform your work in `componentDidMount()` or the other lifecycle methods instead. Keeping `render()` pure makes server rendering more practical and makes components easier to think about.
|
||||
|
||||
|
||||
### getInitialState
|
||||
|
||||
```javascript
|
||||
object getInitialState()
|
||||
```
|
||||
|
||||
Invoked once when the component is mounted. The return value will be used as the initial value of `this.state`.
|
||||
|
||||
|
||||
### getDefaultProps
|
||||
|
||||
```javascript
|
||||
object getDefaultProps()
|
||||
```
|
||||
|
||||
Invoked once when the component is mounted. Values in the mapping will be set on `this.props` if that prop is not specified by the parent component (i.e. using an `in` check).
|
||||
|
||||
This method is invoked before `getInitialState` and therefore cannot rely on `this.state` or use `this.setState`.
|
||||
|
||||
|
||||
### propTypes
|
||||
|
||||
```javascript
|
||||
object propTypes
|
||||
```
|
||||
|
||||
The `propTypes` object allows you to validate props being passed to your components. For more information about `propTypes`, see [Reusable Components](reusable-components.html).
|
||||
|
||||
<!-- TODO: Document propTypes here directly. -->
|
||||
|
||||
|
||||
### mixins
|
||||
|
||||
```javascript
|
||||
array mixins
|
||||
```
|
||||
|
||||
The `mixins` array allows you to use mixins to share behavior among multiple components. For more information about mixins, see [Reusable Components](reusable-components.html).
|
||||
|
||||
<!-- TODO: Document mixins here directly. -->
|
||||
|
||||
|
||||
## Lifecycle Methods
|
||||
|
||||
Various methods are executed at specific points in a component's lifecycle.
|
||||
|
||||
|
||||
### Mounting: componentWillMount
|
||||
|
||||
```javascript
|
||||
componentWillMount()
|
||||
```
|
||||
|
||||
Invoked immediately before rendering occurs. If you call `setState` within this method, `render()` will see the updated state and will be executed only once despite the state change.
|
||||
|
||||
|
||||
### Mounting: componentDidMount
|
||||
|
||||
```javascript
|
||||
componentDidMount(DOMElement rootNode)
|
||||
```
|
||||
|
||||
Invoked immediately after rendering occurs. At this point in the lifecycle, the component has a DOM representation which you can access via the `rootNode` argument or by calling `this.getDOMNode()`.
|
||||
|
||||
If you want to integrate with other JavaScript frameworks, set timers using `setTimeout` or `setInterval`, or send AJAX requests, perform those operations in this method.
|
||||
|
||||
|
||||
### Updating: componentWillReceiveProps
|
||||
|
||||
```javascript
|
||||
componentWillReceiveProps(object nextProps)
|
||||
```
|
||||
|
||||
Invoked when a component is receiving new props. This method is not called for the initial render.
|
||||
|
||||
Use this as an opportunity to react to a prop transition before `render()` is called by updating the state using `this.setState()`. The old props can be accessed via `this.props`. Calling `this.setState()` within this function will not trigger an additional render.
|
||||
|
||||
```javascript
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
this.setState({
|
||||
likesIncreasing: nextProps.likeCount > this.props.likeCount
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
> Note:
|
||||
>
|
||||
> There is no analogous method `componentWillReceiveState`. An incoming prop transition may cause a state change, but the opposite is not true. If you need to perform operations in response to a state change, use `componentWillUpdate`.
|
||||
|
||||
|
||||
### Updating: shouldComponentUpdate
|
||||
|
||||
```javascript
|
||||
boolean shouldComponentUpdate(object nextProps, object nextState)
|
||||
```
|
||||
|
||||
Invoked before rendering when new props or state are being received. This method is not called for the initial render or when `forceUpdate` is used.
|
||||
|
||||
Use this as an opportunity to `return false` when you're certain that the
|
||||
transition to the new props and state will not require a component update.
|
||||
|
||||
```javascript
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
return !equal(nextProps, this.props) || !equal(nextState, this.state);
|
||||
}
|
||||
```
|
||||
|
||||
If `shouldComponentUpdate` returns false, then `render()` will be completely skipped until the next state change. (In addition, `componentWillUpdate` and `componentDidUpdate` will not be called.)
|
||||
|
||||
By default, `shouldComponentUpdate` always returns true to prevent subtle bugs when `state` is mutated in place, but if you are careful to always treat `state` as immutable and to read only from `props` and `state` in `render()` then you can override `shouldComponentUpdate` with an implementation that compares the old props and state to their replacements.
|
||||
|
||||
If performance is a bottleneck, especially with dozens or hundreds of components, use `shouldComponentUpdate` to speed up your app.
|
||||
|
||||
|
||||
### Updating: componentWillUpdate
|
||||
|
||||
```javascript
|
||||
componentWillUpdate(object nextProps, object nextState)
|
||||
```
|
||||
|
||||
Invoked immediately before rendering when new props or state are being received. This method is not called for the initial render.
|
||||
|
||||
Use this as an opportunity to perform preparation before an update occurs.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> You *cannot* use `this.setState()` in this method. If you need to update state in response to a prop change, use `componentWillReceiveProps` instead.
|
||||
|
||||
|
||||
### Updating: componentDidUpdate
|
||||
|
||||
```javascript
|
||||
componentDidUpdate(object prevProps, object prevState, DOMElement rootNode)
|
||||
```
|
||||
|
||||
Invoked immediately after updating occurs. This method is not called for the initial render.
|
||||
|
||||
Use this as an opportunity to operate on the DOM when the component has been updated.
|
||||
|
||||
|
||||
### Unmounting: componentWillUnmount
|
||||
|
||||
```javascript
|
||||
componentWillUnmount()
|
||||
```
|
||||
|
||||
Invoked immediately before a component is unmounted from the DOM.
|
||||
|
||||
Perform any necessary cleanup in this method, such as invalidating timers or cleaning up any DOM elements that were created in `componentDidMount`.
|
||||
65
docs/docs/ref-04-tags-and-attributes.md
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
id: tags-and-attributes
|
||||
title: Tags and Attributes
|
||||
layout: docs
|
||||
permalink: tags-and-attributes.html
|
||||
prev: component-specs.html
|
||||
next: events.html
|
||||
---
|
||||
|
||||
## Supported Tags
|
||||
|
||||
React attempts to support all common elements. If you need an element that isn't listed here, please file an issue.
|
||||
|
||||
The following elements are supported:
|
||||
|
||||
|
||||
### HTML Elements
|
||||
|
||||
```
|
||||
a abbr address area article aside audio b base bdi bdo big blockquote body br
|
||||
button canvas caption cite code col colgroup data datalist dd del details dfn
|
||||
div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6
|
||||
head header hr html i iframe img input ins kbd keygen label legend li link
|
||||
main map mark menu menuitem meta meter nav noscript object ol optgroup option
|
||||
output p param pre progress q rp rt ruby s samp script section select small
|
||||
source span strong style sub summary sup table tbody td textarea tfoot th
|
||||
thead time title tr track u ul var video wbr
|
||||
```
|
||||
|
||||
### SVG elements
|
||||
|
||||
```
|
||||
circle g line path polyline rect svg text
|
||||
```
|
||||
|
||||
|
||||
## Supported Attributes
|
||||
|
||||
React supports all `data-*` and `aria-*` attributes as well as every attribute
|
||||
in the following lists. Note that all attributes are camel-cased and the attributes `class` and `for` are `className` and `htmlFor`, respectively, to match the DOM API specification.
|
||||
|
||||
For a list of events, see [Supported Events](events.html).
|
||||
|
||||
### HTML Attributes
|
||||
|
||||
```
|
||||
accessKey accept action ajaxify allowFullScreen allowTransparency alt
|
||||
autoComplete autoFocus autoPlay cellPadding cellSpacing charSet checked
|
||||
className colSpan content contentEditable contextMenu controls data dateTime
|
||||
dir disabled draggable encType form frameBorder height hidden href htmlFor
|
||||
httpEquiv icon id label lang list max maxLength method min multiple name
|
||||
pattern poster preload placeholder radioGroup rel readOnly required role
|
||||
rowSpan scrollLeft scrollTop selected size spellCheck src step style tabIndex
|
||||
target title type value width wmode
|
||||
```
|
||||
|
||||
In addition, the non-standard `autoCapitalize` attribute is supported for Mobile Safari.
|
||||
|
||||
### SVG Attributes
|
||||
|
||||
```
|
||||
cx cy d fill fx fy points r stroke strokeLinecap strokeWidth transform x x1 x2
|
||||
version viewBox y y1 y2 spreadMethod offset stopColor stopOpacity
|
||||
gradientUnits gradientTransform
|
||||
```
|
||||
205
docs/docs/ref-05-events.md
Normal file
@@ -0,0 +1,205 @@
|
||||
---
|
||||
id: events
|
||||
title: Event System
|
||||
layout: docs
|
||||
permalink: events.html
|
||||
prev: tags-and-attributes.html
|
||||
next: dom-differences.html
|
||||
---
|
||||
|
||||
## SyntheticEvent
|
||||
|
||||
Your event handlers will be passed instances of `SyntheticEvent`, a cross-browser wrapper around the browser's native event. It has the same interface as the browser's native event, including `stopPropagation()` and `preventDefault()`, except the events work identically across all browsers.
|
||||
|
||||
If you find that you need the underlying browser event for some reason, simply use the `nativeEvent` attribute to get it. Every `SyntheticEvent` object has the following attributes:
|
||||
|
||||
```javascript
|
||||
boolean bubbles
|
||||
boolean cancelable
|
||||
DOMEventTarget currentTarget
|
||||
boolean defaultPrevented
|
||||
Number eventPhase
|
||||
boolean isTrusted
|
||||
DOMEvent nativeEvent
|
||||
void preventDefault()
|
||||
void stopPropagation()
|
||||
DOMEventTarget target
|
||||
Date timeStamp
|
||||
String type
|
||||
```
|
||||
|
||||
|
||||
## Supported Events
|
||||
|
||||
React normalizes events so that they have consistent properties across
|
||||
different browsers.
|
||||
|
||||
|
||||
### Clipboard Events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onCopy onCut onPaste
|
||||
```
|
||||
|
||||
Properties:
|
||||
|
||||
```javascript
|
||||
DOMDataTransfer clipboardData
|
||||
```
|
||||
|
||||
|
||||
### Keyboard Events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onKeyDown onKeyPress onKeyUp
|
||||
```
|
||||
|
||||
Properties:
|
||||
|
||||
```javascript
|
||||
boolean altKey
|
||||
String char
|
||||
boolean ctrlKey
|
||||
String key
|
||||
String locale
|
||||
Number location
|
||||
boolean metaKey
|
||||
boolean repeat
|
||||
boolean shiftKey
|
||||
```
|
||||
|
||||
|
||||
### Focus Events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onFocus onBlur
|
||||
```
|
||||
|
||||
Properties:
|
||||
|
||||
```javascript
|
||||
DOMEventTarget relatedTarget
|
||||
```
|
||||
|
||||
|
||||
### Form Events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onChange onInput onSubmit
|
||||
```
|
||||
|
||||
For more information about the onChange event, see [Forms](forms.html).
|
||||
|
||||
|
||||
### Mouse Events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onClick onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave
|
||||
onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
|
||||
onMouseMove onMouseUp
|
||||
```
|
||||
|
||||
Properties:
|
||||
|
||||
```javascript
|
||||
boolean altKey
|
||||
Number button
|
||||
Number buttons
|
||||
Number clientX
|
||||
Number clientY
|
||||
boolean ctrlKey
|
||||
boolean metaKey
|
||||
Number pageX
|
||||
Number pageY
|
||||
DOMEventTarget relatedTarget
|
||||
Number screenX
|
||||
Number screenY
|
||||
boolean shiftKey
|
||||
```
|
||||
|
||||
|
||||
### Mutation Events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onDOMCharacterDataModified
|
||||
```
|
||||
|
||||
Properties:
|
||||
|
||||
```javascript
|
||||
Number attrChange
|
||||
String attrName
|
||||
String newValue
|
||||
String prevValue
|
||||
Node relatedNode
|
||||
```
|
||||
|
||||
|
||||
### Touch events
|
||||
|
||||
To enable touch events, call `React.initializeTouchEvents(true)` before
|
||||
rendering any component.
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onTouchCancel onTouchEnd onTouchMove onTouchStart
|
||||
```
|
||||
|
||||
Properties:
|
||||
|
||||
```javascript
|
||||
boolean altKey
|
||||
DOMTouchList changedTouches
|
||||
boolean ctrlKey
|
||||
boolean metaKey
|
||||
boolean shiftKey
|
||||
DOMTouchList targetTouches
|
||||
DOMTouchList touches
|
||||
```
|
||||
|
||||
|
||||
### UI Events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onScroll
|
||||
```
|
||||
|
||||
Properties:
|
||||
|
||||
```javascript
|
||||
Number detail
|
||||
DOMAbstractView view
|
||||
```
|
||||
|
||||
|
||||
### Wheel Events
|
||||
|
||||
Event names:
|
||||
|
||||
```
|
||||
onWheel
|
||||
```
|
||||
|
||||
Properties:
|
||||
|
||||
```javascript
|
||||
Number deltaX
|
||||
Number deltaMode
|
||||
Number deltaY
|
||||
Number deltaZ
|
||||
```
|
||||
14
docs/docs/ref-06-dom-differences.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
id: dom-differences
|
||||
title: DOM Differences
|
||||
layout: docs
|
||||
permalink: dom-differences.html
|
||||
prev: events.html
|
||||
---
|
||||
|
||||
React has implemented a browser-independent events and DOM system for performance and cross-browser compatibility reasons. We took the opportunity to clean up a few rough edges in browser DOM implementations.
|
||||
|
||||
* All DOM properties and attributes (including event handlers) should be camelCased to be consistent with standard JavaScript style. We intentionally break with the spec here since the spec is inconsistent.
|
||||
* The `style` attribute accepts a JavaScript object with camelCased properties rather than a CSS string. This is consistent with the DOM `style` JavaScript property, is more efficient, and prevents XSS security holes.
|
||||
* All event objects conform to the W3C spec, and all events (including submit) bubble correctly per the W3C spec. See [Event System](events.html) for more details.
|
||||
* The `onChange` event behaves as you would expect it to: whenever a form field is changed this event is fired rather than inconsistently on blur. We intentionally break from existing browser behavior because `onChange` is a misnomer for its behavior and React relies on this event to react to user input in real time. See [Forms](forms.html) for more details.
|
||||
4
docs/docs/reference.html
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
layout: redirect
|
||||
destination: top-level-api.html
|
||||
---
|
||||
@@ -1,11 +1,8 @@
|
||||
---
|
||||
id: docs-tutorial
|
||||
id: tutorial
|
||||
title: Tutorial
|
||||
layout: docs
|
||||
prev: getting-started.html
|
||||
next: common-questions.html
|
||||
---
|
||||
|
||||
We'll be building a simple, but realistic comments box that you can drop into a blog, similar to Disqus, LiveFyre or Facebook comments.
|
||||
|
||||
We'll provide:
|
||||
@@ -20,7 +17,11 @@ It'll also have a few neat features:
|
||||
* **Live updates:** as other users comment we'll pop them into the comment view in real time
|
||||
* **Markdown formatting:** users can use Markdown to format their text
|
||||
|
||||
## Getting started
|
||||
### Want to skip all this and just see the source?
|
||||
|
||||
[It's all on GitHub.](https://github.com/petehunt/react-tutorial)
|
||||
|
||||
### Getting started
|
||||
|
||||
For this tutorial we'll use prebuilt JavaScript files on a CDN. Open up your favorite editor and create a new HTML document:
|
||||
|
||||
@@ -46,7 +47,7 @@ For this tutorial we'll use prebuilt JavaScript files on a CDN. Open up your fav
|
||||
|
||||
For the remainder of this tutorial, we'll be writing our JavaScript code in this script tag.
|
||||
|
||||
## Your first component
|
||||
### Your first component
|
||||
|
||||
React is all about modular, composable components. For our comment box example, we'll have the following component structure:
|
||||
|
||||
@@ -76,7 +77,7 @@ React.renderComponent(
|
||||
);
|
||||
```
|
||||
|
||||
### JSX Syntax
|
||||
#### JSX Syntax
|
||||
|
||||
The first thing you'll notice is the XML-ish syntax in your JavaScript. We have a simple precompiler that translates the syntactic sugar to this plain JavaScript:
|
||||
|
||||
@@ -85,7 +86,7 @@ The first thing you'll notice is the XML-ish syntax in your JavaScript. We have
|
||||
var CommentBox = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
ReactDOM.div({
|
||||
React.DOM.div({
|
||||
className: 'commentBox',
|
||||
children: 'Hello, world! I am a CommentBox.'
|
||||
})
|
||||
@@ -98,19 +99,19 @@ React.renderComponent(
|
||||
);
|
||||
```
|
||||
|
||||
Its use is optional but we've found JSX syntax easier to use than plain JavaScript. Read more on the [JSX Syntax article](syntax.html).
|
||||
Its use is optional but we've found JSX syntax easier to use than plain JavaScript. Read more on the [JSX Syntax article](jsx-in-depth.html).
|
||||
|
||||
### What's going on
|
||||
#### What's going on
|
||||
|
||||
We pass some methods in a JavaScript object to `React.createClass()` to create a new React component. The most important of these methods is called `render` which returns a tree of React components that will eventually render to HTML.
|
||||
|
||||
The `<div>` tags are not actual DOM nodes; they are instantiations of React `div` components. You can think of these as markers or pieces of data that React knows how to handle. React is **safe**. We are not generating HTML strings so XSS protection is the default.
|
||||
|
||||
You do not have to return basic HTML. You can return a tree of components that you (or someone else built). This is what makes React **composable**: a key tenet of maintainable frontends.
|
||||
You do not have to return basic HTML. You can return a tree of components that you (or someone else) built. This is what makes React **composable**: a key tenet of maintainable frontends.
|
||||
|
||||
`React.renderComponent()` instantiates the root component, starts the framework, and injects the markup into a raw DOM element, provided as the second argument.
|
||||
|
||||
# Composing components
|
||||
## Composing components
|
||||
|
||||
Let's build skeletons for `CommentList` and `CommentForm` which will, again, be simple `<div>`s:
|
||||
|
||||
@@ -154,9 +155,9 @@ var CommentBox = React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
Notice how we're mixing HTML tags and components we've built. HTML components are regular React components, just like the ones you define, with one difference. The JSX compiler will automatically rewrite HTML tags to "ReactDOM.tagName" expressions and leave everything else alone. This is to prevent the pollution of the global namespace.
|
||||
Notice how we're mixing HTML tags and components we've built. HTML components are regular React components, just like the ones you define, with one difference. The JSX compiler will automatically rewrite HTML tags to "React.DOM.tagName" expressions and leave everything else alone. This is to prevent the pollution of the global namespace.
|
||||
|
||||
## Component Properties
|
||||
### Component Properties
|
||||
|
||||
Let's create our third component, `Comment`. We will want to pass it the author name and comment text so we can reuse the same code for each unique comment. First let's add some comments to the `CommentList`:
|
||||
|
||||
@@ -176,7 +177,7 @@ var CommentList = React.createClass({
|
||||
|
||||
Note that we have passed some data from the parent `CommentList` component to the child `Comment` component as both XML-like children and attributes. Data passed from parent to child is called **props**, short for properties.
|
||||
|
||||
## Using props
|
||||
### Using props
|
||||
|
||||
Let's create the Comment component. It will read the data passed to it from the CommentList and render some markup:
|
||||
|
||||
@@ -198,11 +199,21 @@ var Comment = React.createClass({
|
||||
|
||||
By surrounding a JavaScript expression in braces inside JSX (as either an attribute or child), you can drop text or React components into the tree. We access named attributes passed to the component as keys on `this.props` and any nested elements as `this.props.children`.
|
||||
|
||||
## Adding Markdown
|
||||
### Adding Markdown
|
||||
|
||||
Markdown is a simple way to format your text inline. For example, surrounding text with asterisks will make it emphasized.
|
||||
|
||||
First, add the third-party **Showdown** library to your application. This is a JavaScript library which takes Markdown text and converts it to raw HTML. This requires a script tag in your head (which we have already included in the React playground).
|
||||
First, add the third-party **Showdown** library to your application. This is a JavaScript library which takes Markdown text and converts it to raw HTML. This requires a script tag in your head (which we have already included in the React playground):
|
||||
|
||||
```html{6}
|
||||
<!-- template.html -->
|
||||
<head>
|
||||
<title>Hello React</title>
|
||||
<script src="http://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="http://fb.me/JSXTransformer-{{site.react_version}}.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
Next, let's convert the comment text to Markdown and output it:
|
||||
|
||||
@@ -251,15 +262,15 @@ This is a special API that intentionally makes it difficult to insert raw HTML,
|
||||
|
||||
**Remember:** by using this feature you're relying on Showdown to be secure.
|
||||
|
||||
## Hook up the data model
|
||||
### Hook up the data model
|
||||
|
||||
So far we've been inserting the comments directly in the source code. Instead, let's render a blob of JSON data into the comment list. Eventually this will come from the server, but for now, write it in your source:
|
||||
|
||||
```javascript
|
||||
// tutorial8.js
|
||||
var data = [
|
||||
{author: 'Pete Hunt', text: 'This is one comment'},
|
||||
{author: 'Jordan Walke', text: 'This is *another* comment'}
|
||||
{author: "Pete Hunt", text: "This is one comment"},
|
||||
{author: "Jordan Walke", text: "This is *another* comment"}
|
||||
];
|
||||
```
|
||||
|
||||
@@ -305,7 +316,7 @@ var CommentList = React.createClass({
|
||||
|
||||
That's it!
|
||||
|
||||
## Fetching from the server
|
||||
### Fetching from the server
|
||||
|
||||
Let's replace the hard-coded data with some dynamic data from the server. We will remove the data prop and replace it with a URL to fetch:
|
||||
|
||||
@@ -313,13 +324,13 @@ Let's replace the hard-coded data with some dynamic data from the server. We wil
|
||||
// tutorial11.js
|
||||
React.renderComponent(
|
||||
<CommentBox url="comments.json" />,
|
||||
document.getElementById('example')
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
This component is different from the prior components because it will have to re-render itself. The component won't have any data until the request from the server comes back, at which point the component may need to render some new comments.
|
||||
|
||||
## Reactive state
|
||||
### Reactive state
|
||||
|
||||
So far, each component has rendered itself once based on its props. `props` are immutable: they are passed from the parent and are "owned" by the parent. To implement interactions, we introduce mutable **state** to the component. `this.state` is private to the component and can be changed by calling `this.setState()`. When the state is updated, the component re-renders itself.
|
||||
|
||||
@@ -327,7 +338,7 @@ So far, each component has rendered itself once based on its props. `props` are
|
||||
|
||||
When the server fetches data, we will be changing the comment data we have. Let's add an array of comment data to the `CommentBox` component as its state:
|
||||
|
||||
```javascript{3-5}
|
||||
```javascript{3-5,10}
|
||||
// tutorial12.js
|
||||
var CommentBox = React.createClass({
|
||||
getInitialState: function() {
|
||||
@@ -347,14 +358,14 @@ var CommentBox = React.createClass({
|
||||
|
||||
`getInitialState()` executes exactly once during the lifecycle of the component and sets up the initial state of the component.
|
||||
|
||||
### Updating state
|
||||
#### Updating state
|
||||
When the component is first created, we want to GET some JSON from the server and update the state to reflect the latest data. In a real application this would be a dynamic endpoint, but for this example, we will use a static JSON file to keep things simple:
|
||||
|
||||
```javascript
|
||||
// tutorial13.json
|
||||
[
|
||||
{'author': 'Pete Hunt', 'text': 'This is one comment'},
|
||||
{'author': 'Jordan Walke', 'text': 'This is *another* comment'}
|
||||
{"author": "Pete Hunt", "text": "This is one comment"},
|
||||
{"author": "Jordan Walke", "text": "This is *another* comment"}
|
||||
]
|
||||
```
|
||||
|
||||
@@ -431,13 +442,13 @@ React.renderComponent(
|
||||
|
||||
```
|
||||
|
||||
All we have done here is move the AJAX call to a separate method and call it when the component is first loaded and every 60 seconds after that. Try running this in your browser and changing the `comments.json` file; within 5 seconds, the changes will show!
|
||||
All we have done here is move the AJAX call to a separate method and call it when the component is first loaded and every 5 seconds after that. Try running this in your browser and changing the `comments.json` file; within 5 seconds, the changes will show!
|
||||
|
||||
## Adding new comments
|
||||
### Adding new comments
|
||||
|
||||
Now it's time to build the form. Our `CommentForm` component should ask the user for their name and comment text and send a request to the server to save the comment.
|
||||
|
||||
```javascript{5-8}
|
||||
```javascript{5-9}
|
||||
// tutorial15.js
|
||||
var CommentForm = React.createClass({
|
||||
render: function() {
|
||||
@@ -445,27 +456,29 @@ var CommentForm = React.createClass({
|
||||
<form class="commentForm">
|
||||
<input type="text" placeholder="Your name" />
|
||||
<input type="text" placeholder="Say something..." />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Let's make the form interactive. When the user presses enter, we should clear the form, submit a request to the server, and refresh the list of comments. To start, let's listen for this event and just clear the form.
|
||||
Let's make the form interactive. When the user submits the form, we should clear it, submit a request to the server, and refresh the list of comments. To start, let's listen for the form's submit event and clear it.
|
||||
|
||||
```javascript{3-12,15,20}
|
||||
```javascript{3-13,16,21}
|
||||
// tutorial16.js
|
||||
var CommentForm = React.createClass({
|
||||
handleSubmit: React.autoBind(function() {
|
||||
handleSubmit: function() {
|
||||
var author = this.refs.author.getDOMNode().value.trim();
|
||||
var text = this.refs.text.getDOMNode().value.trim();
|
||||
if (!text || !author) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// TODO: send request to the server
|
||||
this.refs.author.getDOMNode().value = '';
|
||||
this.refs.text.getDOMNode().value = '';
|
||||
}),
|
||||
return false;
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<form class="commentForm" onSubmit={this.handleSubmit}>
|
||||
@@ -475,29 +488,30 @@ var CommentForm = React.createClass({
|
||||
placeholder="Say something..."
|
||||
ref="text"
|
||||
/>
|
||||
<input type="submit" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### Events
|
||||
##### Events
|
||||
|
||||
React attaches event handlers to components using a camelCase naming convention. We attach an onKeyUp handler to the text field, check if the user has entered text and pressed the enter key and then clear the form fields.
|
||||
React attaches event handlers to components using a camelCase naming convention. We attach an `onSubmit` handler to the form that clears the form fields when the form is submitted with valid input.
|
||||
|
||||
`React.autoBind()` is a simple way to ensure that a method is always bound to its component. Inside the method, `this` will be bound to the component instance.
|
||||
We always return `false` from the event handler to prevent the browser's default action of submitting the form. (If you prefer, you can instead take the event as an argument and call `preventDefault()` on it.)
|
||||
|
||||
#### Refs
|
||||
##### Refs
|
||||
|
||||
We use the `ref` attribute to assign a name to a child component and `this.refs` to reference the component. We can call `getDOMNode()` on a component to get the native browser DOM element.
|
||||
|
||||
#### Callbacks as props
|
||||
##### Callbacks as props
|
||||
|
||||
When a user submits a comment, we will need to refresh the list of comments to include the new one. It makes sense to do all of this logic in `CommentBox` since `CommentBox` owns the state that represents the list of comments.
|
||||
|
||||
We need to pass data from the child component to its parent. We do this by passing a `callback` in props from parent to child:
|
||||
|
||||
```javascript{13-15,30}
|
||||
```javascript{13-15,32}
|
||||
// tutorial17.js
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
@@ -510,9 +524,9 @@ var CommentBox = React.createClass({
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: React.autoBind(function(comment) {
|
||||
handleCommentSubmit: function(comment) {
|
||||
// TODO: submit to the server and refresh the list
|
||||
}),
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
@@ -537,18 +551,19 @@ var CommentBox = React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
Let's call the callback from the `CommentForm` when the user presses enter:
|
||||
Let's call the callback from the `CommentForm` when the user submits the form:
|
||||
|
||||
```javascript{6}
|
||||
// tutorial18.js
|
||||
var CommentForm = React.createClass({
|
||||
handleSubmit: React.autoBind(function() {
|
||||
handleSubmit: function() {
|
||||
var author = this.refs.author.getDOMNode().value.trim();
|
||||
var text = this.refs.text.getDOMNode().value.trim();
|
||||
this.props.onCommentSubmit({author: author, text: text});
|
||||
this.refs.author.getDOMNode().value = '';
|
||||
this.refs.text.getDOMNode().value = '';
|
||||
}),
|
||||
return false;
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<form class="commentForm" onSubmit={this.handleSubmit}>
|
||||
@@ -558,6 +573,7 @@ var CommentForm = React.createClass({
|
||||
placeholder="Say something..."
|
||||
ref="text"
|
||||
/>
|
||||
<input type="submit" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
@@ -579,7 +595,7 @@ var CommentBox = React.createClass({
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: React.autoBind(function(comment) {
|
||||
handleCommentSubmit: function(comment) {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
data: comment,
|
||||
@@ -589,7 +605,7 @@ var CommentBox = React.createClass({
|
||||
this.setState({data: data});
|
||||
}.bind(this)
|
||||
});
|
||||
}),
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
@@ -614,7 +630,7 @@ var CommentBox = React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
## Optimization: optimistic updates
|
||||
### Optimization: optimistic updates
|
||||
|
||||
Our application is now feature complete but it feels slow to have to wait for the request to complete before your comment appears in the list. We can optimistically add this comment to the list to make the app feel faster.
|
||||
|
||||
@@ -631,7 +647,7 @@ var CommentBox = React.createClass({
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: React.autoBind(function(comment) {
|
||||
handleCommentSubmit: function(comment) {
|
||||
var comments = this.state.data;
|
||||
comments.push(comment);
|
||||
this.setState({data: comments});
|
||||
@@ -644,7 +660,7 @@ var CommentBox = React.createClass({
|
||||
this.setState({data: data});
|
||||
}.bind(this)
|
||||
});
|
||||
}),
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
@@ -669,6 +685,6 @@ var CommentBox = React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
## Congrats!
|
||||
### Congrats!
|
||||
|
||||
You have just built a comment box in a few simple steps. Learn more about React in the [reference](syntax.html) or start hacking! Good luck!
|
||||
You have just built a comment box in a few simple steps. Learn more about [why to use React](why-react.html), or dive into the [API reference](top-level-api.html) and start hacking! Good luck!
|
||||
|
||||
@@ -17,16 +17,30 @@ Download the starter kit to get everything you need to
|
||||
#### <a href="http://fb.me/react-{{site.react_version}}.min.js">React Core {{site.react_version}} (production)</a>
|
||||
The compressed, production version of React core
|
||||
|
||||
```html
|
||||
<script src="http://fb.me/react-{{site.react_version}}.min.js"></script>
|
||||
```
|
||||
|
||||
#### <a href="http://fb.me/react-{{site.react_version}}.js">React Core {{site.react_version}} (development)</a>
|
||||
The uncompressed, development version of React core with inline documentation.
|
||||
|
||||
```html
|
||||
<script src="http://fb.me/react-{{site.react_version}}.js"></script>
|
||||
```
|
||||
|
||||
#### <a href="http://fb.me/JSXTransformer-{{site.react_version}}.js">JSX Transform</a>
|
||||
The JSX transformer used to support [XML syntax](/react/docs/syntax.html) in JavaScript.
|
||||
The JSX transformer used to support [XML syntax](/react/docs/jsx-in-depth.html) in JavaScript.
|
||||
|
||||
```html
|
||||
<script src="http://fb.me/JSXTransformer-{{site.react_version}}.js"></script>
|
||||
```
|
||||
|
||||
All scripts are also available via [CDNJS](http://cdnjs.com/#react).
|
||||
|
||||
## Bower
|
||||
|
||||
```sh
|
||||
$ bower install react
|
||||
$ bower install --save react
|
||||
```
|
||||
|
||||
## NPM
|
||||
@@ -35,10 +49,3 @@ $ bower install react
|
||||
$ npm install -g react-tools
|
||||
```
|
||||
|
||||
## Release Notes
|
||||
|
||||
**0.3** Initial public release.
|
||||
|
||||
**0.2** Standardize API & refactor component lifecycle. Normalize DOM interactions.
|
||||
|
||||
**0.1** Initial release.
|
||||
|
||||
21
docs/feed.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
layout: none
|
||||
---
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>{{ site.name }}</title>
|
||||
<description>{{ site.description }}</description>
|
||||
<link>{{ site.url }}{{ site.baseurl }}</link>
|
||||
<atom:link href="{{ site.url }}{{ site.baseurl }}/feed.xml" rel="self" type="application/rss+xml" />
|
||||
{% for post in site.posts limit:10 %}
|
||||
<item>
|
||||
<title>{{ post.title | xml_escape }}</title>
|
||||
<description>{{ post.content | xml_escape }}</description>
|
||||
<pubDate>{{ post.date | date_to_xmlschema }}</pubDate>
|
||||
<link>{{ site.url }}{{ site.baseurl }}{{ post.url }}</link>
|
||||
<guid isPermaLink="true">{{ site.url }}{{ site.baseurl }}{{ post.url }}</guid>
|
||||
</item>
|
||||
{% endfor %}
|
||||
</channel>
|
||||
</rss>
|
||||
BIN
docs/img/blog/chatapp.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
docs/img/blog/dog-tutorial.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
docs/img/blog/khan-academy-editor.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/img/blog/landoflisp.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
docs/img/blog/markdown_refactor.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
docs/img/blog/monkeys.gif
Normal file
|
After Width: | Height: | Size: 532 KiB |
BIN
docs/img/blog/propeller-logo.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
docs/img/blog/quiztime.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/img/blog/react-hackathon.jpg
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
docs/img/blog/react-page.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/img/blog/snake.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
docs/img/blog/todomvc.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
docs/img/blog/turboreact.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
docs/img/blog/unite.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
docs/img/blog/wolfenstein_react.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
docs/img/blog/xreact.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
@@ -3,6 +3,7 @@ layout: page
|
||||
title: A JavaScript library for building user interfaces
|
||||
id: home
|
||||
---
|
||||
|
||||
<section class="light home-section">
|
||||
<div class="marketing-row">
|
||||
<div class="marketing-col">
|
||||
@@ -15,8 +16,8 @@ id: home
|
||||
<div class="marketing-col">
|
||||
<h3>Efficient</h3>
|
||||
<p>
|
||||
React minimizes interactions with the DOM by using a mock representation
|
||||
of the DOM.
|
||||
React computes the minimal set of changes necessary to keep your DOM
|
||||
up-to-date.
|
||||
</p>
|
||||
</div>
|
||||
<div class="marketing-col">
|
||||
@@ -34,29 +35,32 @@ id: home
|
||||
<h3>A Simple Component</h3>
|
||||
<p>
|
||||
React components implement a `render()` method that takes input data and
|
||||
returns what to display. This example constructs the component using an
|
||||
XML-like syntax called JSX. Input data is passed to the component as XML
|
||||
attributes, and `render()` accesses this data via `this.props`.
|
||||
returns what to display. This example uses an XML-like syntax called
|
||||
JSX. Input data that is passed into the component can be accessed by
|
||||
`render()` via `this.props`.<br />
|
||||
<strong>JSX is optional and not required to use React.</strong>
|
||||
</p>
|
||||
<div id="helloExample"></div>
|
||||
</div>
|
||||
<div class="example">
|
||||
<h3>A Stateful Component</h3>
|
||||
<p>
|
||||
In addition to taking data from its creator (accessed via `this.props`),
|
||||
a component can maintain internal state data (accessed via
|
||||
`this.state`). When a component's state data changes, the rendered
|
||||
markup will be updated by re-invoking `render()`.
|
||||
In addition to taking input data (accessed via `this.props`), a
|
||||
component can maintain internal state data (accessed via `this.state`).
|
||||
When a component's state data changes, the rendered markup will be
|
||||
updated by re-invoking `render()`.<br />
|
||||
<strong>This example demonstrates use of React without JSX.</strong>
|
||||
</p>
|
||||
<div id="timerExample"></div>
|
||||
</div>
|
||||
<div class="example">
|
||||
<h3>An Application</h3>
|
||||
<p>
|
||||
Using properties and state, we can put together a small Todo
|
||||
application. React provides an interface to the DOM via `refs`. Although
|
||||
event handlers appear to be rendered inline, they will be
|
||||
collected and implemented using event delegation.
|
||||
Using `props` and `state`, we can put together a small Todo application.
|
||||
This example uses `state` to track the current list of items as well as
|
||||
the text that the user has entered. Although event handlers appear to be
|
||||
rendered inline, they will be collected and implemented using event
|
||||
delegation.
|
||||
</p>
|
||||
<div id="todoExample"></div>
|
||||
</div>
|
||||
|
||||
14
docs/jsx-compiler.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
layout: default
|
||||
title: JSX Compiler Service
|
||||
id: jsx-compiler
|
||||
---
|
||||
<div class="jsxCompiler">
|
||||
<h1>JSX Compiler</h1>
|
||||
<p>
|
||||
This tool demonstrates how <a href="/react/docs/jsx-in-depth.html">JSX syntax</a>
|
||||
is desguared into native JavaScript.
|
||||
</p>
|
||||
<div id="jsxCompiler"></div>
|
||||
<script type="text/javascript" src="js/jsx-compiler.js"></script>
|
||||
</div>
|
||||
@@ -6,10 +6,20 @@ id: support
|
||||
|
||||
**React** is worked on full-time by Facebook's product infrastructure and Instagram's user interface engineering teams. They're often around and available for questions.
|
||||
|
||||
## Stack Overflow
|
||||
|
||||
Many members of the community use Stack Overflow to ask questions. Read through the [existing questions](http://stackoverflow.com/questions/tagged/reactjs) tagged with **reactjs** or [ask your own](http://stackoverflow.com/questions/ask)!
|
||||
|
||||
## Google Groups mailing list
|
||||
|
||||
<a href="http://groups.google.com/group/reactjs" target="_blank">The **reactjs** Google Group</a> is the best place to ask questions and find answers.
|
||||
<a href="http://groups.google.com/group/reactjs" target="_blank">The **reactjs** Google Group</a> is also a good place to ask questions and find answers.
|
||||
|
||||
## IRC
|
||||
|
||||
Many developers and users idle on Freenode.net's IRC network in **[#reactjs on freenode](irc://chat.freenode.net/reactjs)**.
|
||||
|
||||
## Twitter
|
||||
|
||||
[**#reactjs** hash tag on Twitter](https://twitter.com/search?q=%23reactjs) is used to keep up with the latest React news.
|
||||
|
||||
<center><a class="twitter-timeline" data-dnt="true" data-chrome="nofooter noheader transparent" href="https://twitter.com/search?q=%23reactjs" data-widget-id="342522405270470656"></a></center>
|
||||
|
||||
@@ -14,9 +14,9 @@ var BallmerPeakCalculator = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {bac: 0};
|
||||
},
|
||||
handleChange: React.autoBind(function() {
|
||||
this.setState({bac: this.refs.bac.getDOMNode().value});
|
||||
}),
|
||||
handleChange: function(event) {
|
||||
this.setState({bac: event.target.value});
|
||||
},
|
||||
render: function() {
|
||||
var bac;
|
||||
var pct;
|
||||
@@ -33,7 +33,7 @@ var BallmerPeakCalculator = React.createClass({
|
||||
<h4>Compute your Ballmer Peak:</h4>
|
||||
<p>
|
||||
If your BAC is{' '}
|
||||
<input ref="bac" type="text" onKeyUp={this.handleChange} value={this.state.bac} />
|
||||
<input type="text" onChange={this.handleChange} value={this.state.bac} />
|
||||
{', '}then <b>{pct}</b> of your lines of code will have bugs.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<pre>
|
||||
python -m SimpleHTTPServer
|
||||
</pre>
|
||||
and going to <a href="http://localhost:8080/">http://localhost:8080/</a>.
|
||||
and going to <a href="http://localhost:8000/">http://localhost:8000/</a>.
|
||||
</p>
|
||||
</div>
|
||||
<h4>Example Details</h4>
|
||||
|
||||
@@ -4,34 +4,66 @@
|
||||
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
|
||||
<title>Basic Example with external JSX</title>
|
||||
<link rel="stylesheet" href="../shared/css/base.css" />
|
||||
<style type="text/css" media="screen">
|
||||
.codeBox {
|
||||
padding: 7px;
|
||||
overflow:scroll;
|
||||
background-color: #eee;
|
||||
font-weight:normal;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
window.setTimeout(function() {
|
||||
var chromeClientCLI = window.chromeClientCLI;
|
||||
var errorBox = window.errorBox;
|
||||
var chromeErrorFooter = window.chromeErrorFooter;
|
||||
var chromeInstructions = window.chromeInstructions;
|
||||
var isChrome = !!window.chrome;
|
||||
chromeClientCLI.innerText =
|
||||
'open -a "Google Chrome" --new \\\n' +
|
||||
' ' + window.location.href + ' \\\n' +
|
||||
' --args --allow-file-access-from-files --user-data-dir=/tmp';
|
||||
|
||||
errorBox.innerText =
|
||||
isChrome ? 'To run in Chrome, do one of the following:' :
|
||||
'Errors loading page: Check the console.'
|
||||
chromeErrorFooter.innerText =
|
||||
isChrome ? 'If page still does not load, check console.' : '';
|
||||
|
||||
if (!isChrome) {
|
||||
chromeInstructions.innerText = "";
|
||||
}
|
||||
}, 0);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Basic Example with external JSX</h1>
|
||||
<div id="container">
|
||||
<p>
|
||||
If you can see this, React is not working right. This is probably because you're viewing
|
||||
this on your file system instead of a web server. Try running
|
||||
<pre>
|
||||
python -m SimpleHTTPServer
|
||||
</pre>
|
||||
and going to <a href="http://localhost:8080/">http://localhost:8080/</a>.
|
||||
<h4 id="errorBox" style="color: #733"></h4>
|
||||
<ol id="chromeInstructions">
|
||||
<li>
|
||||
Open this page on a Mac via the terminal command:
|
||||
<pre id="chromeClientCLI" class="codeBox">
|
||||
</li>
|
||||
<h4><i>OR</i></h4>
|
||||
<li>
|
||||
Serve this page from a web server
|
||||
<pre id="chromeServerCLI" class="codeBox">
|
||||
cd /Path/To/This/File
|
||||
python -m SimpleHTTPServer
|
||||
open -a "Google Chrome" <a href="http://localhost:8000/">http://localhost:8000/</a>. </pre>
|
||||
</li>
|
||||
</ol>
|
||||
<h4 id="chromeErrorFooter" style="color: #733"></h4>
|
||||
</p>
|
||||
</div>
|
||||
<h4>Example Details</h4>
|
||||
<ul>
|
||||
<li>
|
||||
This is built with
|
||||
<p>
|
||||
Example Details: This is built with
|
||||
<a href="https://github.com/substack/node-browserify">browserify</a>.
|
||||
</li>
|
||||
<li>
|
||||
This is written with JSX in a separate file and transformed in the browser.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
Learn more at
|
||||
<a href="http://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
|
||||
A separate JSX file is transformed in the browser.
|
||||
</p>
|
||||
<script src="../../build/react.js"></script>
|
||||
<script src="../../build/JSXTransformer.js"></script>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div id="container">
|
||||
<p>
|
||||
To install React, follow the instructions on
|
||||
<a href="http://www.github.com/facebook/react.js/">GitHub</a>.
|
||||
<a href="http://www.github.com/facebook/react/">GitHub</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you can see this, React is not running. You probably didn't run:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div id="container">
|
||||
<p>
|
||||
To install React, follow the instructions on
|
||||
<a href="http://www.github.com/facebook/react.js/">GitHub</a>.
|
||||
<a href="http://www.github.com/facebook/react/">GitHub</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you can see this, React is not working right.
|
||||
|
||||