Compare commits

...

113 Commits

Author SHA1 Message Date
Paul O’Shannessy
fef495942a 15.1.0 2016-05-20 15:54:35 -07:00
Paul O’Shannessy
b7d480986a Update readme for 15.1.0 2016-05-20 15:44:48 -07:00
Paul O’Shannessy
da6a30b022 Merge branch '15.1.0-dev' into 15-stable 2016-05-20 15:41:45 -07:00
Paul O’Shannessy
bca912f91e Changelog for 15.1.0 2016-05-20 15:20:11 -07:00
Dan Abramov
5b77fff586 Merge pull request #6753 from facebook/fix-6750
Fix a memory leak in ReactComponentTreeDevtool
(cherry picked from commit de1bb7a71f)
2016-05-19 22:56:28 -07:00
Dan Abramov
95db5bab42 Merge pull request #6752 from facebook/fix-6742
Fix ReactPerf.printOperations() crash
(cherry picked from commit 027d9a919b)
2016-05-19 22:56:22 -07:00
Rachel D. Cartwright
b4c1356d18 make test utils format consistent (#6777)
(cherry picked from commit 207fe0b478)
2016-05-16 13:00:48 -07:00
djskinner
668dd47700 Refer to correct example (#6760)
I *think* this should refer to the second example, where the instance to the ref is stored. In any case please can someone confirm for my own understanding?
(cherry picked from commit 712b1f75bf)
2016-05-16 13:00:43 -07:00
Chad Fawcett
d9bcda01db Add information on JSX element keys (#6751)
(cherry picked from commit 5d64199bb6)
2016-05-16 13:00:33 -07:00
Jarrod Mosen
8c50a04455 Fix grammar on homepage (#6746)
* Fix grammar in README

* Change DOM abstraction grammar on homepage

(cherry picked from commit 01b060d7dc)
2016-05-16 13:00:25 -07:00
hao.huang
80b849e2a0 Add permalink (#6713)
Add permalink to docs, so we can access with 'prev' and 'next'
(cherry picked from commit 92bebcad5f)
2016-05-16 13:00:20 -07:00
Ben Alpert
e15a7d1f7e Revert "Don't wrap drag events in IE/Edge in dev builds" (#6741)
(cherry picked from commit 98cb2f8507)
2016-05-12 11:38:07 -07:00
Paul O’Shannessy
7da8884581 15.1.0-alpha.1 2016-05-09 22:25:33 -07:00
Paul O’Shannessy
871523c8f4 Shrinkwrap to pick up jest upgrade 2016-05-09 22:22:41 -07:00
Dan Abramov
09172b112f Merge pull request #6647 from gaearon/bye-bye-reactperf
Replace ReactPerf with new implementation
(cherry picked from commit b6a6078167)
2016-05-09 22:07:49 -07:00
Desmond Brand
3adc4a6e0e Add links to docs for addons and top level API (#6555)
This makes it easier to figure out where the docs live.

Googling for e.g. `react-addons-update` also works, but this should
make things easier for people that hyperclick directly to the source.
(cherry picked from commit db175052c0)
2016-05-09 22:07:42 -07:00
Ben Alpert
b29bf7515b Fix bug with double updates in a single batch (#6650)
Fixes #2410. Fixes #6371. Fixes #6538.

I also manually tested the codepen in #3762 and verified it now works.
(cherry picked from commit c1e3f7ec14)
2016-05-09 22:05:32 -07:00
Dan Abramov
cba62feeec Merge pull request #6633 from gaearon/native-tree-devtool
Make ReactComponentTreeDevtool work with React Native
(cherry picked from commit 45ec1265eb)
2016-05-09 22:05:16 -07:00
Christoph Pojer
09c6d53e64 Merge pull request #6620 from cpojer/master
Update to Jest 12. Codemod to new Jest APIs.
(cherry picked from commit d07b554291)
2016-05-09 22:05:09 -07:00
Dan Abramov
78aa706491 Merge pull request #6046 from gaearon/new-perf
Add new ReactPerf
(cherry picked from commit 98a8f49068)
2016-05-09 21:54:42 -07:00
Dan Abramov
f50d542ff7 Merge pull request #6612 from gaearon/instrumentation-new-operations
Add ReactNativeOperationHistoryDevtool to track native operations
(cherry picked from commit 3bdf09e86f)
2016-05-09 21:54:36 -07:00
Dan Abramov
583d7205c6 Merge pull request #6549 from gaearon/instrumentation-new
Provide info about component tree to devtools
(cherry picked from commit 76a4c46dba)
2016-05-09 21:54:23 -07:00
Jim
1f1dba92a8 Merge pull request #6364 from p-jackson/issue-5700
Don't wrap drag events in IE/Edge in dev builds
(cherry picked from commit 2e8f28c29f)
2016-05-09 21:54:17 -07:00
Jim
258e591e45 Merge pull request #6341 from borisyankov/master
Add more information to warning 'Input elements must be either controlled or uncontrolled'
(cherry picked from commit 006058daa5)
2016-05-09 21:54:12 -07:00
Jim
42d27cd152 Merge pull request #6134 from richardscarrott/master
Warn if props obj passed into createElement / cloneElement inherits from anything other than Object
(cherry picked from commit 7b47e3e537)
2016-05-09 21:53:51 -07:00
Paul O’Shannessy
d8d6c7a07b 15.0.3-alpha.2 2016-05-09 21:32:13 -07:00
Paul O’Shannessy
4f0163fd38 Ensure babelrc gets added to zipfile too (#6688)
(cherry picked from commit 48f4684b5f)
2016-05-09 21:29:12 -07:00
Jim
0244879c8f Basic SSR support for error boundaries (#6694)
(cherry picked from commit 96cb8c5fc4)
2016-05-09 21:23:44 -07:00
Andreas Svensson
743e4c6231 DOMLazyTree, populate <object> before insertion into DOM (#6691)
(cherry picked from commit 2af4765a2a)
2016-05-09 21:23:38 -07:00
Tanase Hagi
c3d99b5292 Update examples/basic-commonjs/package.json (#6685)
(cherry picked from commit 83521bddb0)
2016-05-09 21:22:54 -07:00
Jake Boone
d1f519e0cd Grammar correction in ReactDOMInput.js warning (#6657)
Changed "a uncontrolled input" to "an uncontrolled input".
(cherry picked from commit 393a1798fa)
2016-05-09 21:19:51 -07:00
Brandon Dail
ff3cec5beb Return early from enqueuePutListener for SSR (#6678)
(cherry picked from commit eb116482a3)
2016-05-09 21:19:42 -07:00
Jan Schär
b0deadc05d Allow custom elements extending native ones (#6570)
...by passing the `is` attribute as the second param to `createElement`.
See http://webcomponents.org/polyfills/custom-elements/
(cherry picked from commit 3d31361cfb)
2016-05-09 21:16:51 -07:00
Dan Abramov
ced4ef9ad6 Fix zh-TW permalink 2016-05-10 02:21:01 +01:00
Dan Abramov
ca19ae5ad0 Fix ru-RU doc page permalinks
Fixes #6735
2016-05-10 01:48:48 +01:00
Dan Abramov
9460263e41 Merge pull request #6730 from elas7/fix-docs
[docs] Remove mention of 'nested object' as an allowed children in React.Children.map
(cherry picked from commit 982e096eb5)
2016-05-09 15:37:45 -07:00
Yaxian
197ecabb9a refine the translation of chapter 12-context (#6665)
(cherry picked from commit 9ddf9e137e)
2016-05-09 15:37:38 -07:00
Dan Abramov
ee459684f1 Merge pull request #6696 from dotu/patch-3
Create 03-interactivity-and-dynamic-uis.ru-RU.md
(cherry picked from commit 590ee490f9)
2016-05-09 15:37:34 -07:00
Kevin Suttle
6516c72ef1 Fix broken link to TypeScript docs (#6687)
(cherry picked from commit 3370db14bb)
2016-05-09 15:37:28 -07:00
Dan Abramov
9d022818e1 Merge pull request #6669 from dotu/patch-2
Create 02-displaying-data.ru-RU.md
(cherry picked from commit 4ed46ec52f)
2016-05-09 15:37:20 -07:00
Andrey Safronov
b9ae9f5f38 Create 01-why-react.ru-RU.md (#6659)
* Create 01-why-react.ru-RU.md

* Create 01-why-react.ru-RU.md

Translation for language code [ru-RU](https://en.wikipedia.org/wiki/Russian_language)

* Create 01-why-react.ru-RU.md

Errors fixes

* Update 01-why-react.ru-RU.md

исправил "чтобы решить".
спасибо за отзывчивость. надеюсь дальнейшие переводы хоть немного помогут распространению React в России :)

(cherry picked from commit 08e568cfc8)
2016-05-09 15:37:16 -07:00
Jackson Huang
b8ac9e1597 Create 01-why-react.zh-TW.md (#6470)
* Create 01-why-react.zh-TW.md

Translation for language code [zh-TW](https://en.wikipedia.org/wiki/Zh-TW)

* Update 01-why-react.zh-TW.md

change "封裝性非常好" to "封裝性高"

(cherry picked from commit 44f84634d7)
2016-05-09 15:37:09 -07:00
Simen Bekkhus
9537b240de Add note on how to submit a form (#6594)
(cherry picked from commit 772468183f)
2016-05-09 15:37:05 -07:00
Dan Abramov
9c6de78844 Merge pull request #6628 from sheerun/patch-1
Document stateless components in formal types
(cherry picked from commit af1a21289b)
2016-05-09 15:36:43 -07:00
Yan Li
6bb4fea31d adds ReactRally & Reactive 2016 + conf locations (#6623)
(cherry picked from commit 71179459de)
2016-05-09 15:36:35 -07:00
z.ky
97849a08cd Update tutorial - add link for starting server (#6602)
To be extra helpful to beginners, and avoid questions like this: http://stackoverflow.com/questions/35758956/react-tutorial-how-do-i-start-the-server
(cherry picked from commit f4e608fc2e)
2016-05-09 15:31:35 -07:00
Paul O’Shannessy
2f435912d8 Shrinkwrap to account for updated object-assign 2016-05-03 12:38:01 -07:00
Paul O’Shannessy
d737dc6dd2 15.0.3-alpha.1 2016-05-03 12:21:33 -07:00
Paul O’Shannessy
1b22f12acd Ensure we're using latest object-assign (#6681)
This picks up the change to feature test against order bugs.
(cherry picked from commit 468901c336)
2016-05-03 12:18:46 -07:00
Pieter De Baets
69bb9e3c8c Remove some mocks that are already packaged by InitializeJavaScriptAppEngine (#6642)
(cherry picked from commit 760b1ef4c3)
2016-05-03 12:03:13 -07:00
Pieter De Baets
772b5f9a5a Move ReactIOS components to native subfolder (#6643)
* Move ReactIOS components to ReactNative
* Drop ReactNative subfolder
(cherry picked from commit 222f5087fe)
2016-05-03 12:02:35 -07:00
Sebastian Markbåge
64acaca8ee Use spread instead of deprecated merge utility (#6634)
(cherry picked from commit 72ba5971ae)
2016-05-03 11:50:28 -07:00
Sebastian Markbåge
0008beb1fb Get rid of transformMatrix/decomposeMatrix special case (#6660)
This is no longer needed on the native side.

This is also the last use of the Platform flag. React Core is now
platform agnostic with regard to React Native. So I'll remove
the mocks and dependency.
(cherry picked from commit 0e4b046634)
2016-05-03 11:44:02 -07:00
Paul O’Shannessy
846b5ea252 Update website for 15.0.2 2016-04-29 17:34:00 -07:00
Paul O’Shannessy
de0b0b3705 15.0.2 2016-04-29 17:32:43 -07:00
Paul O’Shannessy
4dec99c61e Update readme for 15.0.2 2016-04-29 17:28:09 -07:00
Paul O’Shannessy
18d715b86e Merge branch '15.0.2-dev' into 15-stable 2016-04-29 17:27:26 -07:00
Paul O’Shannessy
a157791264 Changelog for 15.0.2 2016-04-29 17:04:18 -07:00
Paul O’Shannessy
590d82bc33 Ensure babelrc file gets packaged for starter kit (#6617)
(cherry picked from commit 096e5c7cf7)
2016-04-28 00:41:34 -07:00
Paul O’Shannessy
a210dacdf4 15.0.2-alpha.4 2016-04-27 23:54:09 -07:00
Jim
1dfaa528f8 ComponentWillUnmount should only ever be invoked once (#6613)
(cherry picked from commit 8dfdac6780)
2016-04-27 23:32:08 -07:00
Esteban
8c811778d6 Fix return type in onlyChild's JSDoc (#6573)
The return type is a 'ReactElement' instead of a 'ReactComponent'.
(cherry picked from commit 416f315c96)
2016-04-27 23:20:27 -07:00
Esteban
395ae75eb3 Fix mapFunction parameters in mapChildren's JSDoc (#6569)
Remove 'key' parameter from 'mapFunction(child, key, index)'. It is no longer called with 'key'.
(cherry picked from commit 9462d0d040)
2016-04-27 23:19:52 -07:00
Ike Peters
2606966b43 properly handling invalid scryRenderedDOMComponentsWithClass args (#6529)
properly handling invalid scryRenderedDOMComponentsWithClass args

properly handle invalid scryRenderedDOMComponentsWithClass args
(cherry picked from commit 9df54e0fce)
2016-04-27 23:19:22 -07:00
Dan Abramov
c98f0e6631 Merge pull request #6516 from gaearon/ignore-dom-writes-outside-batch
Ignore DOM writes outside the batch in ReactPerf
(cherry picked from commit 6a93137f0e)
2016-04-27 23:18:17 -07:00
Paul O’Shannessy
a7714585bb Merge pull request #6504 from alexlur/patch-1
Replaces Array#map with Array#forEach
(cherry picked from commit 932334d3d4)
2016-04-27 23:13:18 -07:00
hkal
da6e4853be Helper for escaping and unescpaing component keys (#6500)
- Abstract escaping
- Provide human readible same key warnings
(cherry picked from commit dc6fc8cc07)
2016-04-27 23:12:19 -07:00
Ben Alpert
afba0f3da7 Merge pull request #6469 from keyanzhang/validate-foreignObject-children
Ensure validateDOMNesting catches nested body elements
(cherry picked from commit 4016e71609)
2016-04-27 23:10:30 -07:00
Jim
d2b947c351 Merge pull request #6462 from Wildhoney/master
Re-added support for attaching events to document fragments
(cherry picked from commit 0b1fd18685)
2016-04-27 23:09:50 -07:00
Jim
d1ba51bc84 Merge pull request #6442 from trevorsmith/master
Correctly select options when nested inside an optgroup
(cherry picked from commit 5ac51c39a0)
2016-04-27 23:06:43 -07:00
Dan Abramov
9d73b2339a Merge pull request #6388 from gaearon/bye-bye-deprecated-utils
Remove OrderedMap and ReactPropTransferer
(cherry picked from commit b8f8360b5c)
2016-04-27 23:05:48 -07:00
Dan Abramov
e88c96b1d7 Merge pull request #6362 from gaearon/no-owner-in-test-utils
Elements from functional components in TestUtils should have no owner
(cherry picked from commit ae56910573)
2016-04-27 22:59:40 -07:00
Dan Abramov
3655e30adb Merge pull request #6215 from nhunzaker/nh-fix-disabled-inputs
Disabled inputs should not respond to clicks in IE
(cherry picked from commit 36e4fe54a8)
2016-04-27 22:54:46 -07:00
Paul O’Shannessy
112a400662 15.0.2-alpha.3 2016-04-25 12:55:13 -07:00
Sebastian Markbåge
33a9603e93 Ignore events fired on missing React Native instances
This can happen if something gets unmounted before the event gets
dispatched. I'm not sure how this works out exactly but this
preserves previous behavior in this scenario.
(cherry picked from commit 69b6869a3e)
2016-04-25 12:53:02 -07:00
Sebastian Markbåge
ae6dfa9dae Merge pull request #6588 from sahrens/patch-3
Delete ReactNativeGlobalInteractionHandler.js
(cherry picked from commit 2f2ed71bd0)
2016-04-25 12:52:52 -07:00
Sebastian Markbåge
c05ae26ec8 Merge pull request #6587 from sahrens/patch-2
Move PanResponder back to react-native repo temporarily.
(cherry picked from commit ea504521d5)
2016-04-25 12:52:46 -07:00
Sebastian Markbåge
3b2f29ef69 Merge pull request #6584 from sahrens/patch-1
[RN] Don't hold interaction handles for all touches
(cherry picked from commit aacb5467a0)
2016-04-25 12:52:41 -07:00
Denis Laxalde
ecb61403d7 Remove mention of deprecated ReactLink add-on (#6535)
(cherry picked from commit de7d1da997)
2016-04-22 13:13:07 -07:00
Paul O’Shannessy
9eb37bff49 Merge pull request #6519 from zpao/envdocsfixup
Cleanup environments doc
(cherry picked from commit befb70e42f)
2016-04-22 13:12:02 -07:00
Minwei Xu
605109021f ref-09-webcomponents.zh-CN.md (#6561)
(cherry picked from commit b7a2409919)
2016-04-22 13:11:55 -07:00
Adrian Sieber
a3b7699f42 Minor fixes (#6527)
* Fix typos in CHANGELOG.md

* Fix typos in 2014-11-24-react-js-conf-updates.md

(cherry picked from commit 8156ee0cab)
2016-04-22 13:11:48 -07:00
Jim
3251460ebd Mention Enzyme on the test utils page. (#6523)
(cherry picked from commit a12aab10cb)
2016-04-22 13:11:31 -07:00
Paul O’Shannessy
ec036ed185 Merge pull request #6576 from yuji0602/tutorial_md_sample_json_change
Changed example json value.
2016-04-22 10:40:18 -07:00
yuji0602
5922ea1a0c Changed example json value. 2016-04-22 13:38:01 +09:00
Ben Alpert
1fb7d64171 15.0.2-alpha.2 2016-04-21 15:18:27 -07:00
Ben Alpert
fd8aa077e3 Merge pull request #6572 from spicyj/rn-batch
Batch event handling in React Native
2016-04-21 15:15:19 -07:00
Paul O’Shannessy
3e8a2aaddb 15.0.2-alpha.1 2016-04-20 10:37:33 -07:00
Paul O’Shannessy
c81c29ae58 Merge pull request #6553 from zpao/cleanuppkg
Clean up package.json after #6338
(cherry picked from commit bddecc9696)
2016-04-20 10:37:03 -07:00
Sebastian Markbåge
5b4b6e7999 Merge pull request #6338 from sebmarkbage/reactnative2
Move React Core Integration and Injection to the Core Repo
(cherry picked from commit c84ad52ddb)
2016-04-20 09:39:50 -07:00
Jim
f565c92e38 Added docs for environment integration.
(cherry picked from commit 66bfee6543)
2016-04-14 12:32:35 -07:00
Jim
fc4bf8158a Create section on using React with package managers.
(cherry picked from commit c01c46b88a)
2016-04-14 12:31:31 -07:00
Dan Abramov
7cd3aa7a1e Use the same changelog format as 15.0 post 2016-04-08 23:01:15 +01:00
Jim
ab4057880e Merge pull request #6443 from Aweary/patch-1
Grammar fix for 15.0 blog post
(cherry picked from commit 09022b165f)
2016-04-08 11:29:06 -07:00
Paul O’Shannessy
d72885b383 Actually bump version on website 2016-04-08 11:28:52 -07:00
Paul O’Shannessy
fd1476e3aa Update website for 15.0.1 2016-04-08 11:22:55 -07:00
Paul O’Shannessy
142e4ebb57 15.0.1 blog post 2016-04-08 11:12:26 -07:00
Paul O’Shannessy
ca92b9104c 15.0.1 2016-04-08 11:12:25 -07:00
Paul O’Shannessy
a6179d03f3 Update changelog & readme for 15.0.1 2016-04-08 11:12:25 -07:00
Ben Alpert
8afaf0380f Merge pull request #6449 from spicyj/option-value
Set value using attribute only on initial option render
(cherry picked from commit 2b1bd1d7fe)
2016-04-07 21:47:58 -07:00
Paul O’Shannessy
ca0c409b6f Merge pull request #6444 from zpao/re__spreadwarn
Add back React.__spread and make it warn
(cherry picked from commit 516c1d809e)
2016-04-07 17:49:05 -07:00
Paul O’Shannessy
177796ff79 Fix extraneous markup in changelog 2016-04-07 17:49:05 -07:00
Paul O’Shannessy
da3be881ba [docs] Clarify data-reactid in v15 post
(cherry picked from commit 6fd2b29ec8)
2016-04-07 15:27:37 -07:00
Dan Abramov
1a0ec77094 Add the missing download
(cherry picked from commit 1aee28ef1b)
2016-04-07 14:33:05 -07:00
Jim
e226021c5e Merge pull request #6400 from jimfb/return-value-legacy
Document legacyness of the return value of ReactDOM.render()
(cherry picked from commit 1dc7c581db)
2016-04-07 14:28:20 -07:00
Jim
1942c6a035 Merge pull request #6419 from IvanVergiliev/master
Add documentation about empty functional components
(cherry picked from commit 62f64a84a4)
2016-04-07 14:28:14 -07:00
Paul O’Shannessy
c49166401a Update readme for v15 2016-04-07 13:59:21 -07:00
Paul O’Shannessy
500c0003b2 Update Changelog for v15 2016-04-07 13:58:15 -07:00
Paul O’Shannessy
0275d77fc0 [docs] Update site for v15 2016-04-07 13:58:15 -07:00
Dan Abramov
67a4b12e27 Add React 15 post 2016-04-07 13:58:14 -07:00
Paul O’Shannessy
d1c08f11d5 v15.0.0 2016-04-07 12:07:50 -07:00
Paul O’Shannessy
40c0867f63 [docs] Update acknowledgements for v15 2016-04-07 12:04:24 -07:00
Paul O’Shannessy
7081a85ace Shrinkwrap for release branch 2016-04-07 11:55:23 -07:00
192 changed files with 30975 additions and 7379 deletions

View File

@@ -4,6 +4,7 @@
"plugins": [
"fbjs-scripts/babel-6/dev-expression",
"syntax-trailing-function-commas",
"babel-plugin-transform-object-rest-spread",
"transform-es2015-template-literals",
"transform-es2015-literals",
"transform-es2015-arrow-functions",

View File

@@ -58,6 +58,7 @@ script:
-F "react-dom-server.min=@build/react-dom-server.min.js" \
-F "npm-react=@build/packages/react.tgz" \
-F "npm-react-dom=@build/packages/react-dom.tgz" \
-F "npm-react-native=@build/packages/react-native-renderer.tgz" \
-F "commit=$TRAVIS_COMMIT" \
-F "date=`git log --format='%ct' -1`" \
-F "pull_request=$TRAVIS_PULL_REQUEST" \

View File

@@ -1,3 +1,144 @@
## 15.1.0 (May 20, 2016)
### React
- Ensure we're using the latest `object-assign`, which has protection against a non-spec-compliant native `Object.assign`. ([@zpao](https://github.com/zpao) in [#6681](https://github.com/facebook/react/pull/6681))
- Add a new warning to communicate that `props` objects passed to `createElement` must be plain objects. ([@richardscarrott](https://github.com/richardscarrott) in [#6134](https://github.com/facebook/react/pull/6134))
- Fix a batching bug resulting in some lifecycle methods incorrectly being called multiple times. ([@spicyj](https://github.com/spicyj) in [#6650](https://github.com/facebook/react/pull/6650))
### React DOM
- Fix regression in custom elements support. ([@jscissr](https://github.com/jscissr) in [#6570](https://github.com/facebook/react/pull/6570))
- Stop incorrectly warning about using `onScroll` event handler with server rendering. ([@Aweary](https://github.com/Aweary) in [#6678](https://github.com/facebook/react/pull/6678))
- Fix grammar in the controlled input warning. ([@jakeboone02](https://github.com/jakeboone02) in [#6657](https://github.com/facebook/react/pull/6657))
- Fix issue preventing `<object>` nodes from being able to read `<param>` nodes in IE. ([@syranide](https://github.com/syranide) in [#6691](https://github.com/facebook/react/pull/6691))
- Fix issue resulting in crash when using experimental error boundaries with server rendering. ([@jimfb](https://github.com/jimfb) in [#6694](https://github.com/facebook/react/pull/6694))
- Add additional information to the controlled input warning. ([@borisyankov](https://github.com/borisyankov) in [#6341](https://github.com/facebook/react/pull/6341))
### React Perf Add-on
- Completely rewritten to collect data more accurately and to be easier to maintain. ([@gaearon](https://github.com/gaearon) in [#6647](https://github.com/facebook/react/pull/6647), [#6046](https://github.com/facebook/react/pull/6046))
### React Native Renderer
- Remove some special cases for platform specific branching. ([@sebmarkbage](https://github.com/sebmarkbage) in [#6660](https://github.com/facebook/react/pull/6660))
- Remove use of `merge` utility. ([@sebmarkbage](https://github.com/sebmarkbage) in [#6634](https://github.com/facebook/react/pull/6634))
- Renamed some modules to better indicate usage ([@javache](https://github.com/javache) in [#6643](https://github.com/facebook/react/pull/6643))
## 15.0.2 (April 29, 2016)
### React
- Removed extraneous files from npm package. ([@gaearon](https://github.com/gaearon) in [#6388](https://github.com/facebook/react/pull/6388))
- Ensure `componentWillUnmount` is only called once. ([@jimfb](https://github.com/jimfb) in [#6613](https://github.com/facebook/react/pull/6613))
### ReactDOM
- Fixed bug resulting in disabled buttons responding to mouse events in IE. ([@nhunzaker](https://github.com/nhunzaker) in [#6215](https://github.com/facebook/react/pull/6215))
- Ensure `<option>`s are correctly selected when inside `<optgroup>`. ([@trevorsmith](https://github.com/trevorsmith) in [#6442](https://github.com/facebook/react/pull/6442))
- Restore support for rendering into a shadow root. ([@Wildhoney](https://github.com/Wildhoney) in [#6462](https://github.com/facebook/react/pull/6462))
- Ensure nested `<body>` elements are caught when warning for invalid markup. ([@keyanzhang](https://github.com/keyanzhang) in [#6469](https://github.com/facebook/react/pull/6469))
- Improve warning when encountering multiple elements with the same key. ([@hkal](https://github.com/hkal) in [#6500](https://github.com/facebook/react/pull/6500))
### React TestUtils Add-on
- Ensure that functional components do not have an owner. ([@gaearon](https://github.com/gaearon) in [#6362](https://github.com/facebook/react/pull/6362))
- Handle invalid arguments to `scryRenderedDOMComponentsWithClass` better. ([@ipeters90](https://github.com/ipeters90) in [#6529](https://github.com/facebook/react/pull/6529))
### React Perf Add-on
- Ignore DOM operations that occur outside the batch operation. ([@gaearon](https://github.com/gaearon) in [#6516](https://github.com/facebook/react/pull/6516))
### React Native Renderer
- These files are now shipped inside the React npm package. They have no impact on React core or ReactDOM.
## 15.0.1 (April 8, 2016)
### React
- Restore `React.__spread` API to unbreak code compiled with some tools making use of this undocumented API. It is now officially deprecated. ([@zpao](https://github.com/zpao) in [#6444](https://github.com/facebook/react/pull/6444))
### ReactDOM
- Fixed issue resulting in loss of cursor position in controlled inputs. ([@spicyj](https://github.com/spicyj) in [#6449](https://github.com/facebook/react/pull/6449))
## 15.0.0 (April 7, 2016)
### Major changes
- **Initial render now uses `document.createElement` instead of generating HTML.** Previously we would generate a large string of HTML and then set `node.innerHTML`. At the time, this was decided to be faster than using `document.createElement` for the majority of cases and browsers that we supported. Browsers have continued to improve and so overwhelmingly this is no longer true. By using `createElement` we can make other parts of React faster. ([@spicyj](https://github.com/spicyj) in [#5205](https://github.com/facebook/react/pull/5205))
- **`data-reactid` is no longer on every node.** As a result of using `document.createElement`, we can prime the node cache as we create DOM nodes, allowing us to skip a potential lookup (which used the `data-reactid` attribute). Root nodes will have a `data-reactroot` attribute and server generated markup will still contain `data-reactid`. ([@spicyj](https://github.com/spicyj) in [#5205](https://github.com/facebook/react/pull/5205))
- **No more extra `<span>`s.** ReactDOM will now render plain text nodes interspersed with comment nodes that are used for demarcation. This gives us the same ability to update individual pieces of text, without creating extra nested nodes. If you were targeting these `<span>`s in your CSS, you will need to adjust accordingly. You can always render them explicitly in your components. ([@mwiencek](https://github.com/mwiencek) in [#5753](https://github.com/facebook/react/pull/5753))
- **Rendering `null` now uses comment nodes.** Previously `null` would render to `<noscript>` elements. We now use comment nodes. This may cause issues if making use of `:nth-child` CSS selectors. While we consider this rendering behavior an implementation detail of React, it's worth noting the potential problem. ()[@spicyj](https://github.com/spicyj) in [#5451](https://github.com/facebook/react/pull/5451))
- **Functional components can now return `null`.** We added support for [defining stateless components as functions](/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components) in React 0.14. However, React 0.14 still allowed you to define a class component without extending `React.Component` or using `React.createClass()`, so [we couldnt reliably tell if your component is a function or a class](https://github.com/facebook/react/issues/5355), and did not allow returning `null` from it. This issue is solved in React 15, and you can now return `null` from any component, whether it is a class or a function. ([@jimfb](https://github.com/jimfb) in [#5884](https://github.com/facebook/react/pull/5884))
- **Improved SVG support.** All SVG tags are now fully supported. (Uncommon SVG tags are not present on the `React.DOM` element helper, but JSX and `React.createElement` work on all tag names.) All SVG attributes that are implemented by the browsers should be supported too. If you find any attributes that we have missed, please [let us know in this issue](https://github.com/facebook/react/issues/1657). ([@zpao](https://github.com/zpao) in [#6243](https://github.com/facebook/react/pull/6243))
### Breaking changes
- **No more extra `<span>`s.**
- **`React.cloneElement()` now resolves `defaultProps`.** We fixed a bug in `React.cloneElement()` that some components may rely on. If some of the `props` received by `cloneElement()` are `undefined`, it used to return an element with `undefined` values for those props. Were changing it to be consistent with `createElement()`. Now any `undefined` props passed to `cloneElement()` are resolved to the corresponding components `defaultProps`. ([@truongduy134](https://github.com/truongduy134) in [#5997](https://github.com/facebook/react/pull/5997))
- **`ReactPerf.getLastMeasurements()` is opaque.** This change wont affect applications but may break some third-party tools. We are [revamping `ReactPerf` implementation](https://github.com/facebook/react/pull/6046) and plan to release it during the 15.x cycle. The internal performance measurement format is subject to change so, for the time being, we consider the return value of `ReactPerf.getLastMeasurements()` an opaque data structure that should not be relied upon. ([@gaearon](https://github.com/gaearon) in [#6286](https://github.com/facebook/react/pull/6286))
#### Removed deprecations
These deprecations were introduced nine months ago in v0.14 with a warning and are removed:
- Deprecated APIs are removed from the `React` top-level export: `findDOMNode`, `render`, `renderToString`, `renderToStaticMarkup`, and `unmountComponentAtNode`. As a reminder, they are now available on `ReactDOM` and `ReactDOMServer`. ([@jimfb](https://github.com/jimfb) in [#5832](https://github.com/facebook/react/pull/5832))
- Deprecated addons are removed: `batchedUpdates` and `cloneWithProps`. ([@jimfb](https://github.com/jimfb) in [#5859](https://github.com/facebook/react/pull/5859), [@zpao](https://github.com/zpao) in [#6016](https://github.com/facebook/react/pull/6016))
- Deprecated component instance methods are removed: `setProps`, `replaceProps`, and `getDOMNode`. ([@jimfb](https://github.com/jimfb) in [#5570](https://github.com/facebook/react/pull/5570))
- Deprecated CommonJS `react/addons` entry point is removed. As a reminder, you should use separate `react-addons-*` packages instead. This only applies if you use the CommonJS builds. ([@gaearon](https://github.com/gaearon) in [#6285](https://github.com/facebook/react/pull/6285))
- Passing `children` to void elements like `<input>` was deprecated, and now throws an error. ([@jonhester](https://github.com/jonhester) in [#3372](https://github.com/facebook/react/pull/3372))
- React-specific properties on DOM `refs` (e.g. `this.refs.div.props`) were deprecated, and are removed now. ([@jimfb](https://github.com/jimfb) in [#5495](https://github.com/facebook/react/pull/5495))
### New deprecations, introduced with a warning
Each of these changes will continue to work as before with a new warning until the release of React 16 so you can upgrade your code gradually.
- `LinkedStateMixin` and `valueLink` are now deprecated due to very low popularity. If you need this, you can use a wrapper component that implements the same behavior: [react-linked-input](https://www.npmjs.com/package/react-linked-input). ([@jimfb](https://github.com/jimfb) in [#6127](https://github.com/facebook/react/pull/6127))
- Future versions of React will treat `<input value={null}>` as a request to clear the input. However, React 0.14 has been ignoring `value={null}`. React 15 warns you on a `null` input value and offers you to clarify your intention. To fix the warning, you may explicitly pass an empty string to clear a controlled input, or pass `undefined` to make the input uncontrolled. ([@antoaravinth](https://github.com/antoaravinth) in [#5048](https://github.com/facebook/react/pull/5048))
- `ReactPerf.printDOM()` was renamed to `ReactPerf.printOperations()`, and `ReactPerf.getMeasurementsSummaryMap()` was renamed to `ReactPerf.getWasted()`. ([@gaearon](https://github.com/gaearon) in [#6287](https://github.com/facebook/react/pull/6287))
### New helpful warnings
- If you use a minified copy of the _development_ build, React DOM kindly encourages you to use the faster production build instead. ([@spicyj](https://github.com/spicyj) in [#5083](https://github.com/facebook/react/pull/5083))
- React DOM: When specifying a unit-less CSS value as a string, a future version will not add `px` automatically. This version now warns in this case (ex: writing `style={{'{{'}}width: '300'}}`. Unitless *number* values like `width: 300` are unchanged. ([@pluma](https://github.com/pluma) in [#5140](https://github.com/facebook/react/pull/5140))
- Synthetic Events will now warn when setting and accessing properties (which will not get cleared appropriately), as well as warn on access after an event has been returned to the pool. ([@kentcdodds](https://github.com/kentcdodds) in [#5940](https://github.com/facebook/react/pull/5940) and [@koba04](https://github.com/koba04) in [#5947](https://github.com/facebook/react/pull/5947))
- Elements will now warn when attempting to read `ref` and `key` from the props. ([@prometheansacrifice](https://github.com/prometheansacrifice) in [#5744](https://github.com/facebook/react/pull/5744))
- React will now warn if you pass a different `props` object to `super()` in the constructor. ([@prometheansacrifice](https://github.com/prometheansacrifice) in [#5346](https://github.com/facebook/react/pull/5346))
- React will now warn if you call `setState()` inside `getChildContext()`. ([@raineroviir](https://github.com/raineroviir) in [#6121](https://github.com/facebook/react/pull/6121))
- React DOM now attempts to warn for mistyped event handlers on DOM elements, such as `onclick` which should be `onClick`. ([@ali](https://github.com/ali) in [#5361](https://github.com/facebook/react/pull/5361))
- React DOM now warns about `NaN` values in `style`. ([@jontewks](https://github.com/jontewks) in [#5811](https://github.com/facebook/react/pull/5811))
- React DOM now warns if you specify both `value` and `defaultValue` for an input. ([@mgmcdermott](https://github.com/mgmcdermott) in [#5823](https://github.com/facebook/react/pull/5823))
- React DOM now warns if an input switches between being controlled and uncontrolled. ([@TheBlasfem](https://github.com/TheBlasfem) in [#5864](https://github.com/facebook/react/pull/5864))
- React DOM now warns if you specify `onFocusIn` or `onFocusOut` handlers as they are unnecessary in React. ([@jontewks](https://github.com/jontewks) in [#6296](https://github.com/facebook/react/pull/6296))
- React now prints a descriptive error message when you pass an invalid callback as the last argument to `ReactDOM.render()`, `this.setState()`, or `this.forceUpdate()`. ([@conorhastings](https://github.com/conorhastings) in [#5193](https://github.com/facebook/react/pull/5193) and [@gaearon](https://github.com/gaearon) in [#6310](https://github.com/facebook/react/pull/6310))
- Add-Ons: `TestUtils.Simulate()` now prints a helpful message if you attempt to use it with shallow rendering. ([@conorhastings](https://github.com/conorhastings) in [#5358](https://github.com/facebook/react/pull/5358))
- PropTypes: `arrayOf()` and `objectOf()` provide better error messages for invalid arguments. ([@chicoxyzzy](https://github.com/chicoxyzzy) in [#5390](https://github.com/facebook/react/pull/5390))
### Notable bug fixes
- Fixed multiple small memory leaks. ([@spicyj](https://github.com/spicyj) in [#4983](https://github.com/facebook/react/pull/4983) and [@victor-homyakov](https://github.com/victor-homyakov) in [#6309](https://github.com/facebook/react/pull/6309))
- Input events are handled more reliably in IE 10 and IE 11; spurious events no longer fire when using a placeholder. ([@jquense](https://github.com/jquense) in [#4051](https://github.com/facebook/react/pull/4051))
- The `componentWillReceiveProps()` lifecycle method is now consistently called when `context` changes. ([@milesj](https://github.com/milesj) in [#5787](https://github.com/facebook/react/pull/5787))
- `React.cloneElement()` doesnt append slash to an existing `key` when used inside `React.Children.map()`. ([@ianobermiller](https://github.com/ianobermiller) in [#5892](https://github.com/facebook/react/pull/5892))
- React DOM now supports the `cite` and `profile` HTML attributes. ([@AprilArcus](https://github.com/AprilArcus) in [#6094](https://github.com/facebook/react/pull/6094) and [@saiichihashimoto](https://github.com/saiichihashimoto) in [#6032](https://github.com/facebook/react/pull/6032))
- React DOM now supports `cssFloat`, `gridRow` and `gridColumn` CSS properties. ([@stevenvachon](https://github.com/stevenvachon) in [#6133](https://github.com/facebook/react/pull/6133) and [@mnordick](https://github.com/mnordick) in [#4779](https://github.com/facebook/react/pull/4779))
- React DOM now correctly handles `borderImageOutset`, `borderImageWidth`, `borderImageSlice`, `floodOpacity`, `strokeDasharray`, and `strokeMiterlimit` as unitless CSS properties. ([@rofrischmann](https://github.com/rofrischmann) in [#6210](https://github.com/facebook/react/pull/6210) and [#6270](https://github.com/facebook/react/pull/6270))
- React DOM now supports the `onAnimationStart`, `onAnimationEnd`, `onAnimationIteration`, `onTransitionEnd`, and `onInvalid` events. Support for `onLoad` has been added to `object` elements. ([@tomduncalf](https://github.com/tomduncalf) in [#5187](https://github.com/facebook/react/pull/5187), [@milesj](https://github.com/milesj) in [#6005](https://github.com/facebook/react/pull/6005), and [@ara4n](https://github.com/ara4n) in [#5781](https://github.com/facebook/react/pull/5781))
- React DOM now defaults to using DOM attributes instead of properties, which fixes a few edge case bugs. Additionally the nullification of values (ex: `href={null}`) now results in the forceful removal, no longer trying to set to the default value used by browsers in the absence of a value. ([@syranide](https://github.com/syranide) in [#1510](https://github.com/facebook/react/pull/1510))
- React DOM does not mistakingly coerce `children` to strings for Web Components. ([@jimfb](https://github.com/jimfb) in [#5093](https://github.com/facebook/react/pull/5093))
- React DOM now correctly normalizes SVG `<use>` events. ([@edmellum](https://github.com/edmellum) in [#5720](https://github.com/facebook/react/pull/5720))
- React DOM does not throw if a `<select>` is unmounted while its `onChange` handler is executing. ([@sambev](https://github.com/sambev) in [#6028](https://github.com/facebook/react/pull/6028))
- React DOM does not throw in Windows 8 apps. ([@Andrew8xx8](https://github.com/Andrew8xx8) in [#6063](https://github.com/facebook/react/pull/6063))
- React DOM does not throw when asynchronously unmounting a child with a `ref`. ([@yiminghe](https://github.com/yiminghe) in [#6095](https://github.com/facebook/react/pull/6095))
- React DOM no longer forces synchronous layout because of scroll position tracking. ([@syranide](https://github.com/syranide) in [#2271](https://github.com/facebook/react/pull/2271))
- `Object.is` is used in a number of places to compare values, which leads to fewer false positives, especially involving `NaN`. In particular, this affects the `shallowCompare` add-on. ([@chicoxyzzy](https://github.com/chicoxyzzy) in [#6132](https://github.com/facebook/react/pull/6132))
- Add-Ons: ReactPerf no longer instruments adding or removing an event listener because they dont really touch the DOM due to event delegation. ([@antoaravinth](https://github.com/antoaravinth) in [#5209](https://github.com/facebook/react/pull/5209))
### Other improvements
- React now uses `loose-envify` instead of `envify` so it installs less transitive dependencies. ([@qerub](https://github.com/qerub) in [#6303](https://github.com/facebook/react/pull/6303))
- Shallow renderer now exposes `getMountedInstance()`. ([@glenjamin](https://github.com/glenjamin) in [#4918](https://github.com/facebook/react/pull/4918))
- Shallow renderer now returns the rendered output from `render()`. ([@simonewebdesign](https://github.com/simonewebdesign) in [#5411](https://github.com/facebook/react/pull/5411))
- React no longer depends on ES5 *shams* for `Object.create` and `Object.freeze` in older environments. It still, however, requires ES5 *shims* in those environments. ([@dgreensp](https://github.com/dgreensp) in [#4959](https://github.com/facebook/react/pull/4959))
- React DOM now allows `data-` attributes with names that start with numbers. ([@nLight](https://github.com/nLight) in [#5216](https://github.com/facebook/react/pull/5216))
- React DOM adds a new `suppressContentEditableWarning` prop for components like [Draft.js](https://facebook.github.io/draft-js/) that intentionally manage `contentEditable` children with React. ([@mxstbr](https://github.com/mxstbr) in [#6112](https://github.com/facebook/react/pull/6112))
- React improves the performance for `createClass()` on complex specs. ([@spicyj](https://github.com/spicyj) in [#5550](https://github.com/facebook/react/pull/5550))
## 0.14.8 (March 29, 2016)
### React
@@ -88,7 +229,7 @@
### Major changes
- Split the main `react` package into two: `react` and `react-dom`. This paves the way to writing components that can be shared between the web version of React and React Native. This means you will need to include both files and some functions have been moved from `React` to `ReactDOM`.
- Addons have been moved to seperate packages (`react-addons-clone-with-props`, `react-addons-create-fragment`, `react-addons-css-transition-group`, `react-addons-linked-state-mixin`, `react-addons-perf`, `react-addons-pure-render-mixin`, `react-addons-shallow-compare`, `react-addons-test-utils`, `react-addons-transition-group`, `react-addons-update`, `ReactDOM.unstable_batchedUpdates`).
- Addons have been moved to separate packages (`react-addons-clone-with-props`, `react-addons-create-fragment`, `react-addons-css-transition-group`, `react-addons-linked-state-mixin`, `react-addons-perf`, `react-addons-pure-render-mixin`, `react-addons-shallow-compare`, `react-addons-test-utils`, `react-addons-transition-group`, `react-addons-update`, `ReactDOM.unstable_batchedUpdates`).
- Stateless functional components - React components were previously created using React.createClass or using ES6 classes. This release adds a [new syntax](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions) where a user defines a single [stateless render function](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions) (with one parameter: `props`) which returns a JSX element, and this function may be used as a component.
- Refs to DOM components as the DOM node itself. Previously the only useful thing you can do with a DOM component is call `getDOMNode()` to get the underlying DOM node. Starting with this release, a ref to a DOM component _is_ the actual DOM node. **Note that refs to custom (user-defined) components work exactly as before; only the built-in DOM components are affected by this change.**

View File

@@ -74,6 +74,10 @@ module.exports = function(grunt) {
grunt.registerTask('npm-react-dom:release', npmReactDOMTasks.buildRelease);
grunt.registerTask('npm-react-dom:pack', npmReactDOMTasks.packRelease);
var npmReactNativeTasks = require('./grunt/tasks/npm-react-native');
grunt.registerTask('npm-react-native:release', npmReactNativeTasks.buildRelease);
grunt.registerTask('npm-react-native:pack', npmReactNativeTasks.packRelease);
var npmReactAddonsTasks = require('./grunt/tasks/npm-react-addons');
grunt.registerTask('npm-react-addons:release', npmReactAddonsTasks.buildReleases);
grunt.registerTask('npm-react-addons:pack', npmReactAddonsTasks.packReleases);
@@ -127,6 +131,8 @@ module.exports = function(grunt) {
'npm-react:pack',
'npm-react-dom:release',
'npm-react-dom:pack',
'npm-react-native:release',
'npm-react-native:pack',
'npm-react-addons:release',
'npm-react-addons:pack',
'compare_size',

View File

@@ -37,12 +37,12 @@ The fastest way to get started is to serve JavaScript from the CDN (also availab
```html
<!-- The core React library -->
<script src="https://fb.me/react-0.14.8.js"></script>
<script src="https://fb.me/react-15.1.0.js"></script>
<!-- The ReactDOM Library -->
<script src="https://fb.me/react-dom-0.14.8.js"></script>
<script src="https://fb.me/react-dom-15.1.0.js"></script>
```
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-0.14.8.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-15.1.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.
If you'd like to use [bower](http://bower.io), it's as easy as:

View File

@@ -36,13 +36,13 @@ sass:
sass_dir: _css
gems:
- jekyll-redirect-from
react_version: 0.14.7
react_version: 15.0.2
react_hashes:
dev: xQae1pUPdAKUe0u0KUTNt09zzdwheX4VSUsV8vatqM+t6X7rta01qOzessL808ox
prod: zTm/dblzLXQNp3CgY+hfaC/WJ6h4XtNrePh2CW2+rO9GPuNiPb9jmthvAL+oI/dQ
addons_dev: I5TF2q2QDmB31aN5lcClArdUo+WJH/Yi3hcH3PBVXFe5DYtYCFh7Jx/dmpba12zn
addons_prod: KPHTQfiYMhtsIRbZcY4ri1lBYZQbj4ePsSdzODR2Bu5L5ts3APVyqwKPBThO5Hgc
dom_dev: A1t0GCrR06cTHvMjaxeSE8XOiz6j7NvWdmxhN/9z748wEvJTVk13Rr8gMzTUnd8G
dom_prod: ntqCsHbLdMxT352UbhPbT7fqjE8xi4jLmQYQa8mYR+ylAapbXRfdsDweueDObf7m
dom_server_dev: 3I5+eGB/ILYa6pQQX+rM9O0SyDltamM40RiZ5JvIijSYEfVGZU0vY4Iwx9a1eYyD
dom_server_prod: Kt9dEqXzv00orFPW2o3H+kxQtSiNO8EqXsXJT3i99rCcp74N/Km98V0kUxAzy44k
dev: dedPNF++oHBwT++5v2VMeXSzyNkqJd7tbc3ic+wN3l0u/NEBcMNuf9a7knYgwTco
prod: 1kql9Cm3anPpO0n0a4T7keJt+N4pixvMU33Bk69kZi1WkN6gbq1EVZdfZLjqwmFq
addons_dev: b7jdy0/iqeUofUONQyRN/Y3DO/h61sL56BgMXJzfokC2mtsi2pJGhQekw6QqI/71
addons_prod: 1J/3e0bGfmFbeuWDRmyBoBOImeFnDn03OKWsXiWVOThql8Yf1qXaim7NrAqL4RHi
dom_dev: kQ+9o036IWQT7tKVxA8siLqHR0DekC3YXbkA7RsFQHbuqQutOmb3cOsTQ1WFtMhW
dom_prod: q14dOJErroITWJ+DFXug03tOxuZ4fm7u5BkcbboXFWJNvDGPepPWXUuIphvvAsAl
dom_server_dev: WiRnBunlOqqLKTWNe+788pJ0QLFIXXktwBnqNV2OggmTROfZJvn1WfrZyh0xhnja
dom_server_prod: wkSOmc5KBqBSFy+CAVk0ehSoBEMqzpKj4lzcoKLBchNzTIwCAZ3Pe+LX73kyNNhz

View File

@@ -2,17 +2,21 @@
- - '839'
- Aaron Franks
- Aaron Gelter
- Adam Bloomston
- Adam Krebs
- Adam Mark
- Adam Solove
- Adam Timberlake
- Adam Zapletal
- Ahmad Wali Sidiqi
- Alan Plum
- Alan Souza
- Alan deLevie
- Alastair Hole
- Alex
- Alex Boatwright
- Alex Boyd
- Alex Dajani
- Alex Lopatin
- Alex Mykyta
- Alex Pien
@@ -24,22 +28,28 @@
- Alexandre Gaudencio
- Alexey Raspopov
- Alexey Shamrin
- Ali Ukani
- Andre Z Sanchez
- Andreas Savvides
- Andreas Svensson
- Andres Kalle
- Andres Suarez
- Andrew Clark
- Andrew Cobby
- Andrew Davey
- Andrew Henderson
- Andrew Kulakov
- Andrew Rasmussen
- Andrew Sokolov
- Andrew Zich
- Andrey Popp
- Anthony van der Hoorn
- Anto Aravinth
- Antonio Ruberto
- Antti Ahti
- Anuj Tomar
- AoDev
- April Arcus
- Areeb Malik
- Aria Buckles
- Aria Stewart
@@ -54,7 +64,9 @@
- Beau Smith
- Ben Alpert
- Ben Anderson
- Ben Brooks
- Ben Foxall
- Ben Halpern
- Ben Jaffe
- Ben Moss
- Ben Newman
@@ -62,16 +74,20 @@
- Benjamin Keen
- Benjamin Leiken
- Benjamin Woodruff
- Benjy Cui
- Bill Blanchard
- Bill Fisher
- Blaine Hatab
- Blaine Kasten
- Bob Eagan
- Bob Ralian
- Bob Renwick
- Bobby
- Bojan Mihelac
- Bradley Spaulding
- Brandon Bloom
- Brandon Tilley
- Brenard Cubacub
- Brian Cooke
- Brian Holt
- Brian Hsu
@@ -82,14 +98,19 @@
- Bruno Škvorc
- Cam Song
- Cam Spiers
- Cameron Chamberlain
- Cameron Matheson
- Carter Chung
- Cassus Adam Banko
- Cat Chen
- Cedric Sohrauer
- Cesar William Alvarenga
- Changsoon Bok
- Charles Marsh
- Chase Adams
- Cheng Lou
- Chitharanjan Das
- Chris Bolin
- Chris Grovers
- Chris Ha
- Chris Rebert
@@ -97,12 +118,15 @@
- Christian Alfoni
- Christian Oliff
- Christian Roman
- Christoffer Sawicki
- Christoph Pojer
- Christopher Monsanto
- Clay Allsopp
- Connor McSheffrey
- Conor Hastings
- Cory House
- Cotton Hou
- Craig Akimoto
- Cristovao Verstraeten
- Damien Pellier
- Dan Abramov
@@ -113,6 +137,7 @@
- Daniel Friesen
- Daniel Gasienica
- Daniel Hejl
- Daniel Hejl
- Daniel Lo Nigro
- Daniel Mané
- Daniel Miladinov
@@ -122,23 +147,31 @@
- Darcy
- Daryl Lau
- Darío Javier Cravero
- Dave Galbraith
- David Baker
- David Ed Mellum
- David Goldberg
- David Granado
- David Greenspan
- David Hellsing
- David Hu
- David Khourshid
- David Mininger
- David Neubauer
- David Percy
- Dean Shi
- Denis Sokolov
- Deniss Jacenko
- Dennis Johnson
- Devon Blandin
- Devon Harvey
- Dmitrii Abramov
- Dmitriy Rozhkov
- Dmitry Blues
- Dmitry Mazuro
- Domenico Matteo
- Don Abrams
- Dongsheng Liu
- Dustan Kasten
- Dustin Getz
- Dylan Harrington
@@ -154,6 +187,7 @@
- Erik Harper
- Espen Hovlandsdal
- Evan Coonrod
- Evan Vosberg
- Fabio M. Costa
- Federico Rampazzo
- Felipe Oliveira Carvalho
@@ -163,11 +197,15 @@
- Frankie Bagnardi
- François-Xavier Bois
- Fred Zhao
- Freddy Rangel
- Fyodor Ivanishchev
- G Scott Olson
- G. Kay Lee
- Gabe Levi
- Gajus Kuizinas
- Gareth Nicholson
- Garren Smith
- Gavin McQuistin
- Geert Pasteels
- Geert-Jan Brits
- George A Sisco III
@@ -183,44 +221,57 @@
- Guido Bouman
- Harry Hull
- Harry Marr
- - Harry Moreno
- Harry Moreno
- Harshad Sabne
- Hekar Khani
- Hendrik Swanepoel
- Henrik Nyh
- Henry Wong
- Henry Zhu
- Hideo Matsumoto
- Hou Chia
- Huang-Wei Chang
- - Hugo Agbonon
- Hugo Jobling
- Hyeock Kwon
- Héliton Nordt
- Ian Obermiller
- Ignacio Carbajo
- Igor Scekic
- Ilia Pavlenkov
- Ilya Shuklin
- Ilyá Belsky
- Ingvar Stepanyan
- Irae Carvalho
- Isaac Salier-Hellendag
- Iurii Kucherov
- Ivan Kozik
- Ivan Krechetov
- Ivan Vergiliev
- J. Andrew Brassington
- J. Renée Beach
- JD Isaacks
- JJ Weber
- JW
- Jack Zhang
- Jackie Wung
- Jacob Gable
- Jacob Greenleaf
- Jae Hun Ro
- Jaeho Lee
- Jaime Mingo
- Jake Worth
- Jakub Malinowski
- James
- James Brantly
- James Burnett
- James Friend
- James Ide
- James Long
- James Pearce
- James Seppi
- James South
- James Wen
- Jamie Wong
- Jamis Charles
- Jamison Dance
@@ -246,6 +297,7 @@
- Jeff Morrison
- Jeff Welch
- Jeffrey Lin
- Jeremy Fairbank
- Jesse Skinner
- Jignesh Kakadiya
- Jim OBrien
@@ -253,14 +305,19 @@
- Jimmy Jea
- Jing Chen
- Jinwoo Oh
- Jinxiu Lee
- Jiyeon Seo
- Jody McIntyre
- Joe Critchley
- Joe Stein
- Joel Auterson
- Johannes Baiter
- Johannes Emerich
- Johannes Lumpe
- John Heroy
- John Ryan
- John Watson
- John-David Dalton
- Jon Beebe
- Jon Chester
- Jon Hester
@@ -270,6 +327,7 @@
- Jonas Enlund
- Jonas Gebhardt
- Jonathan Hsu
- Jonathan Persson
- Jordan Harband
- Jordan Walke
- Jorrit Schippers
@@ -277,7 +335,9 @@
- Joseph Savona
- Josh Bassett
- Josh Duck
- Josh Perez
- Josh Yudaken
- Joshua Evans
- Joshua Go
- Joshua Goldberg
- Joshua Ma
@@ -286,23 +346,34 @@
- Julen Ruiz Aizpuru
- Julian Viereck
- Julien Bordellier
- Julio Lopez
- Jun Wu
- Juraj Dudak
- Justas Brazauskas
- Justin Jaffray
- Justin Robison
- Justin Woo
- Kale
- Kamron Batman
- Karl Mikkelsen
- Karpich Dmitry
- Keito Uchiyama
- Ken Powers
- Kent C. Dodds
- Kevin Cheng
- Kevin Coughlin
- Kevin Huang
- Kevin Lau
- Kevin Old
- Kevin Robinson
- Kewei Jiang
- Kier Borromeo
- KimCoding
- Kirk Steven Hansen
- Kit Randel
- Kohei TAKATA
- Koo Youngmin
- Krystian Karczewski
- Kunal Mehta
- Kurt Ruppel
- Kyle Kelley
@@ -312,6 +383,7 @@
- Lee Byron
- Lee Jaeyoung
- Lei
- Leland Richardson
- Leon Fedotov
- Leon Yip
- Leonardo YongUk Kim
@@ -319,9 +391,13 @@
- Levi McCallum
- Lily
- Logan Allen
- Lovisa Svallingson
- Ludovico Fischer
- Luigy Leon
- Luke Horvat
- MIKAMI Yoshiyuki
- Maher Beg
- Manas
- Marcin K.
- Marcin Kwiatkowski
- Marcin Szczepanski
@@ -331,59 +407,83 @@
- Mark Funk
- Mark Hintz
- Mark IJbema
- Mark Murphy
- Mark Richardson
- Mark Rushakoff
- Mark Sun
- Marlon Landaverde
- Marshall Roch
- Martin Andert
- Martin Hujer
- Martin Jul
- Martin Konicek
- Martin Mihaylov
- Masaki KOBAYASHI
- Mathieu M-Gosselin
- Mathieu Savy
- Matias Singers
- Matsunoki
- Matt Brookes
- Matt Dunn-Rankin
- Matt Harrison
- Matt Huggins
- Matt Stow
- Matt Zabriskie
- Matthew Dapena-Tretter
- Matthew Herbst
- Matthew Hodgson
- Matthew Johnston
- Matthew King
- Matthew Looi
- Matthew Miner
- Matthias Le Brun
- Matti Nelimarkka
- Mattijs Kneppers
- Max F. Albrecht
- Max Heiber
- Max Stoiber
- Maxi Ferreira
- Maxim Abramchuk
- Merrick Christensen
- Mert Kahyaoğlu
- Michael Chan
- Michael McDermott
- Michael Randers-Pehrson
- Michael Ridgway
- Michael Warner
- Michael Wiencek
- Michael Ziwisky
- Michal Srb
- Michelle Todd
- Mihai Parparita
- Mike D Pilsbury
- - Mike Groseclose
- Mike Groseclose
- Mike Nordick
- Mikolaj Dadela
- Miles Johnson
- Minwe LUO
- Miorel Palii
- Morhaus
- - Morhaus
- Moshe Kolodny
- Mouad Debbar
- Murad
- Murray M. Moss
- Nadeesha Cabral
- Naman Goel
- Nate Hunzaker
- Nate Lee
- Nathan Smith
- Nathan White
- Nee
- Neri Marschik
- Nguyen Truong Duy
- Nicholas Bergson-Shilcock
- Nicholas Clawson
- Nick Balestra
- Nick Fitzgerald
- Nick Gavalas
- Nick Merwin
- Nick Presta
- Nick Raienko
- Nick Thompson
- Nick Williams
@@ -399,8 +499,10 @@
- Pablo Lacerda de Miranda
- Paolo Moretti
- Pascal Hartig
- Patrick
- Patrick Laughlin
- Patrick Stapleton
- Paul Benigeri
- Paul Harper
- Paul OShannessy
- Paul Seiffert
@@ -410,19 +512,25 @@
- Peter Blazejewicz
- Peter Cottle
- Peter Jaros
- Peter Newnham
- Petri Lehtinen
- Petri Lievonen
- Pieter Vanderwerff
- Pouja Nikray
- Prathamesh Sonpatki
- Prayag Verma
- Preston Parry
- Rafael
- Rafal Dittwald
- Rainer Oviir
- Rajat Sehgal
- Rajiv Tirumalareddy
- Ram Kaniyur
- Randall Randall
- Ray
- Raymond Ha
- Reed Loden
- Remko Tronçon
- Richard D. Worth
- Richard Feldman
- Richard Kho
@@ -430,16 +538,22 @@
- Richard Livesey
- Richard Wood
- Rick Beerendonk
- Rick Ford
- Riley Tomasek
- Rob Arnold
- Robert Binna
- Robert Knight
- Robert Sedovsek
- Robin Berjon
- Robin Frischmann
- Roman Pominov
- Roman Vanesyan
- Russ
- Ryan Seddon
- Sahat Yalkabov
- Saif Hakim
- Saiichi Hashimoto
- Sam Beveridge
- Sam Saccone
- Sam Selikoff
- Samy Al Zahrani
@@ -448,7 +562,9 @@
- Scott Feeney
- Sean Kinsey
- Sebastian Markbåge
- Sebastian McKenzie
- Seoh Char
- Sercan Eraslan
- Serg
- Sergey Generalov
- Sergey Rubanov
@@ -457,18 +573,25 @@
- Shaun Trennery
- ShihChi Huang
- Shim Won
- Shinnosuke Watanabe
- Shogun Sea
- Shota Kubota
- Shripad K
- Sibi
- Simen Bekkhus
- Simon Højberg
- Simon Welsh
- Simone Vittori
- Soichiro Kawamura
- Sophia Westwood
- Sota Ohara
- Spencer Handley
- Stefan Dombrowski
- Stephen Murphy
- Sterling Cobb
- Steve Baker
- Steven Luscher
- Steven Vachon
- Stoyan Stefanov
- Sundeep Malladi
- Sunny Juneja
@@ -479,9 +602,11 @@
- Taeho Kim
- Tay Yang Shun
- Ted Kim
- Tengfei Guo
- Teodor Szente
- Thomas Aylott
- Thomas Boyt
- Thomas Broadley
- Thomas Reggi
- Thomas Röggla
- Thomas Shaddox
@@ -491,12 +616,15 @@
- Tim Routowicz
- Tim Schaub
- Timothy Yung
- Timur Carpeev
- Tobias Reiss
- Tom Duncalf
- Tom Haggie
- Tom Hauburger
- Tom MacWright
- Tom Occhino
- Tomasz Kołodziejski
- Tomoya Suzuki
- Tony Spiro
- Toru Kobayashi
- Trinh Hoang Nhu
@@ -507,14 +635,17 @@
- Varun Rau
- Vasiliy Loginevskiy
- Victor Alvarez
- Victor Homyakov
- Victor Koenders
- Ville Immonen
- Vincent Riemer
- Vincent Siao
- Vipul A M
- Vitaly Kramskikh
- Vitor Balocco
- Vjeux
- Volkan Unsal
- Wander Wang
- Wayne Larsen
- WickyNilliams
- Wincent Colaiuta
@@ -526,9 +657,14 @@
- YouBao Nong
- Yuichi Hagio
- Yuriy Dybskiy
- Yutaka Nakajima
- Yuval Dekel
- Zach Bruggeman
- Zach Ramaekers
- Zacharias
- Zeke Sikelianos
- Zhangjd
- adraeth
- arush
- brafdlog
- chen
@@ -539,14 +675,23 @@
- dongmeng.ldm
- iamchenxin
- iamdoron
- iawia002
- imagentleman
- koh-taka
- kohashi85
- laiso
- leeyoungalias
- li.li
- maxprafferty
- rgarifullin
- songawee
- sugarshin
- wali-s
- yiminghe
- youmoo
- zhangjg
- Árni Hermann Reynisson
- 凌恒
- 张敏
- zwhitchcox
- "Árni Hermann Reynisson"
- "元彦"
- "凌恒"
- "张敏"

View File

@@ -48,6 +48,13 @@
title: Refs to Components
- id: tooling-integration
title: Tooling Integration
subitems:
- id: language-tooling
title: Language Tooling
- id: package-management
title: Package Management
- id: environments
title: Server-side Environments
- id: addons
title: Add-Ons
subitems:

View File

@@ -10,7 +10,7 @@ amazed that 600 people requested to be notified when ticket go on sale. This is
When we organized the conference, we decided to start small since this is the
first React.js conference. Also, we weren't sure what level of demand to expect,
so we planned for a single-track, two-day conference on Facebook's campus. The
largest room available would accomodate 18 speaking slots and 200 attendees.
largest room available would accommodate 18 speaking slots and 200 attendees.
The spacial configuration makes it difficult to add a second track and changing
venues only two months in advance would be too difficult, so we are deciding to
stick with the originally planned format and venue on Facebook's campus.

View File

@@ -0,0 +1,259 @@
---
title: "React v15.0"
author: gaearon
---
We would like to thank the React community for reporting issues and regressions in the release candidates on our [issue tracker](https://github.com/facebook/react/issues/). Over the last few weeks we fixed those issues, and now, after two release candidates, we are excited to finally release the stable version of React 15.
As a reminder, [were switching to major versions](/react/blog/2016/02/19/new-versioning-scheme.html) to indicate that we have been using React in production for a long time. This 15.0 release follows our previous 0.14 version and well continue to follow semver like weve been doing since 2013. Its also worth noting that [we no longer actively support Internet Explorer 8](/react/blog/2016/01/12/discontinuing-ie8-support.html). We believe React will work in its current form there but we will not be prioritizing any efforts to fix new issues that only affect IE8.
React 15 brings significant improvements to how we interact with the DOM:
* We are now using `document.createElement` instead of setting `innerHTML` when mounting components. This allows us to get rid of the `data-reactid` attribute on every node and make the DOM lighter. Using `document.createElement` is also faster in modern browsers and fixes a number of edge cases related to SVG elements and running multiple copies of React on the same page.
* Historically our support for SVG has been incomplete, and many tags and attributes were missing. We heard you, and in React 15 we [added support for all the SVG attributes that are recognized by todays browsers](https://github.com/facebook/react/pull/6243). If we missed any of the attributes youd like to use, please [let us know](https://github.com/facebook/react/issues/1657). As a bonus, thanks to using `document.createElement`, we no longer need to maintain a list of SVG tags, so any SVG tags that were previously unsupported should work just fine in React 15.
* We received some amazing contributions from the community in this release, and we would like to highlight [this pull request](https://github.com/facebook/react/pull/5753) by [Michael Wiencek](https://github.com/mwiencek) in particular. Thanks to Michaels work, React 15 no longer emits extra `<span>` nodes around the text, making the DOM output much cleaner. This was a longstanding annoyance for React users so its exciting to accept this as an outside contribution.
While this isnt directly related to the release, we understand that in order to receive more community contributions like Michaels, we need to communicate our goals and priorities more openly, and review pull requests more decisively. As a first step towards this, we started publishing [React core team weekly meeting notes](https://github.com/reactjs/core-notes) again. We also intend to introduce an RFC process inspired by [Ember RFCs](https://github.com/emberjs/rfcs) so external contributors can have more insight and influence in the future development of React. We will keep you updated about this on our blog.
We are also experimenting with a new changelog format in this post. Every change now links to the corresponding pull request and mentions the author. Let us know whether you find this useful!
## Upgrade Guide
As usual with major releases, React 15 will remove support for some of the patterns deprecated nine months ago in React 0.14. We know changes can be painful (the Facebook codebase has over 20,000 React components, and thats not even counting React Native), so we always try to make changes gradually in order to minimize the pain.
If your code is free of warnings when running under React 0.14, upgrading should be easy. The bulk of changes in this release are actually behind the scenes, impacting the way that React interacts with the DOM. The other substantial change is that React now supports the full range of SVG elements and attributes. Beyond that we have a large number of incremental improvements and additional warnings aimed to aid developers. Weve also laid some groundwork in the core to bring you some new capabilities in future releases.
See the changelog below for more details.
## Installation
We recommend using React from `npm` and using a tool like browserify or webpack to build your code into a single bundle. To install the two packages:
* `npm install --save react react-dom`
Remember that by default, React runs extra checks and provides helpful warnings in development mode. When deploying your app, set the `NODE_ENV` environment variable to `production` to use the production build of React which does not include the development warnings and runs significantly faster.
If you cant use `npm` yet, we provide pre-built browser builds for your convenience, which are also available in the `react` package on bower.
* **React**
Dev build with warnings: <https://fb.me/react-15.0.0.js>
Minified build for production: <https://fb.me/react-15.0.0.min.js>
* **React with Add-Ons**
Dev build with warnings: <https://fb.me/react-with-addons-15.0.0.js>
Minified build for production: <https://fb.me/react-with-addons-15.0.0.min.js>
* **React DOM** (include React in the page before React DOM)
Dev build with warnings: <https://fb.me/react-dom-15.0.0.js>
Minified build for production: <https://fb.me/react-dom-15.0.0.min.js>
## Changelog
### Major changes
- #### `document.createElement` is in and `data-reactid` is out
There were a number of large changes to our interactions with the DOM. One of the most noticeable changes is that we no longer set the `data-reactid` attribute for each DOM node. While this will make it more difficult to know if a website is using React, the advantage is that the DOM is much more lightweight. This change was made possible by us switching to use `document.createElement` on initial render. Previously we would generate a large string of HTML and then set `node.innerHTML`. At the time, this was decided to be faster than using `document.createElement` for the majority of cases and browsers that we supported. Browsers have continued to improve and so overwhelmingly this is no longer true. By using `createElement` we can make other parts of React faster. The ids were used to map back from events to the original React component, meaning we had to do a bunch of work on every event, even though we cached this data heavily. As weve all experienced, caching and in particularly invalidating caches, can be error prone and we saw many hard to reproduce issues over the years as a result. Now we can build up a direct mapping at render time since we already have a handle on the node.
**Note:** `data-reactid` is still present for server-rendered content, however it is much smaller than before and is simply an auto-incrementing counter.
<small>[@spicyj](https://github.com/spicyj) in [#5205](https://github.com/facebook/react/pull/5205)</small>
- #### No more extra `<span>`s
Another big change with our DOM interaction is how we render text blocks. Previously you may have noticed that React rendered a lot of extra `<span>`s. For example, in our most basic example on the home page we render `<div>Hello {this.props.name}</div>`, resulting in markup that contained 2 `<span>`s. Now well render plain text nodes interspersed with comment nodes that are used for demarcation. This gives us the same ability to update individual pieces of text, without creating extra nested nodes. Very few people have depended on the actual markup generated here so its likely you are not impacted. However if you were targeting these `<span>`s in your CSS, you will need to adjust accordingly. You can always render them explicitly in your components.
<small>[@mwiencek](https://github.com/mwiencek) in [#5753](https://github.com/facebook/react/pull/5753)</small>
- #### Rendering `null` now uses comment nodes
Weve also made use of these comment nodes to change what `null` renders to. Rendering to `null` was a feature we added in React 0.11 and was implemented by rendering `<noscript>` elements. By rendering to comment nodes now, theres a chance some of your CSS will be targeting the wrong thing, specifically if you are making use of `:nth-child` selectors. Reacts use of the `<noscript>` tag has always been considered an implementation detail of how React targets the DOM. We believe they are safe changes to make without going through a release with warnings detailing the subtle differences as they are details that should not be depended upon. Additionally, we have seen that these changes have improved React performance for many typical applications.
<small>[@spicyj](https://github.com/spicyj) in [#5451](https://github.com/facebook/react/pull/5451)</small>
- #### Functional components can now return `null` too
We added support for [defining stateless components as functions](/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components) in React 0.14. However, React 0.14 still allowed you to define a class component without extending `React.Component` or using `React.createClass()`, so [we couldnt reliably tell if your component is a function or a class](https://github.com/facebook/react/issues/5355), and did not allow returning `null` from it. This issue is solved in React 15, and you can now return `null` from any component, whether it is a class or a function.
<small>[@jimfb](https://github.com/jimfb) in [#5884](https://github.com/facebook/react/pull/5884)</small>
- #### Improved SVG support
All SVG tags are now fully supported. (Uncommon SVG tags are not present on the `React.DOM` element helper, but JSX and `React.createElement` work on all tag names.) All SVG attributes that are implemented by the browsers should be supported too. If you find any attributes that we have missed, please [let us know in this issue](https://github.com/facebook/react/issues/1657).
<small>[@zpao](https://github.com/zpao) in [#6243](https://github.com/facebook/react/pull/6243)</small>
### Breaking changes
- #### No more extra `<span>`s
Its worth calling out the DOM structure changes above again, in particular the change from `<span>`s. In the course of updating the Facebook codebase, we found a very small amount of code that was depending on the markup that React generated. Some of these cases were integration tests like WebDriver which were doing very specific XPath queries to target nodes. Others were simply tests using `ReactDOM.renderToStaticMarkup` and comparing markup. Again, there were a very small number of changes that had to be made, but we dont want anybody to be blindsided. We encourage everybody to run their test suites when upgrading and consider alternative approaches when possible. One approach that will work for some cases is to explicitly use `<span>`s in your `render` method.
<small>[@mwiencek](https://github.com/mwiencek) in [#5753](https://github.com/facebook/react/pull/5753)</small>
- #### `React.cloneElement()` now resolves `defaultProps`
We fixed a bug in `React.cloneElement()` that some components may rely on. If some of the `props` received by `cloneElement()` are `undefined`, it used to return an element with `undefined` values for those props. In React 15, were changing it to be consistent with `createElement()`. Now any `undefined` props passed to `cloneElement()` are resolved to the corresponding components `defaultProps`. Only one of our 20,000 React components was negatively affected by this so we feel comfortable releasing this change without keeping the old behavior for another release cycle.
<small>[@truongduy134](https://github.com/truongduy134) in [#5997](https://github.com/facebook/react/pull/5997)</small>
- #### `ReactPerf.getLastMeasurements()` is opaque
This change wont affect applications but may break some third-party tools. We are [revamping `ReactPerf` implementation](https://github.com/facebook/react/pull/6046) and plan to release it during the 15.x cycle. The internal performance measurement format is subject to change so, for the time being, we consider the return value of `ReactPerf.getLastMeasurements()` an opaque data structure that should not be relied upon.
<small>[@gaearon](https://github.com/gaearon) in [#6286](https://github.com/facebook/react/pull/6286)</small>
- #### Removed deprecations
These deprecations were introduced nine months ago in v0.14 with a warning and are removed:
- Deprecated APIs are removed from the `React` top-level export: `findDOMNode`, `render`, `renderToString`, `renderToStaticMarkup`, and `unmountComponentAtNode`. As a reminder, they are now available on `ReactDOM` and `ReactDOMServer`.
<small>[@jimfb](https://github.com/jimfb) in [#5832](https://github.com/facebook/react/pull/5832)</small>
- Deprecated addons are removed: `batchedUpdates` and `cloneWithProps`.
<small>[@jimfb](https://github.com/jimfb) in [#5859](https://github.com/facebook/react/pull/5859), [@zpao](https://github.com/zpao) in [#6016](https://github.com/facebook/react/pull/6016)</small>
- Deprecated component instance methods are removed: `setProps`, `replaceProps`, and `getDOMNode`.
<small>[@jimfb](https://github.com/jimfb) in [#5570](https://github.com/facebook/react/pull/5570)</small>
- Deprecated CommonJS `react/addons` entry point is removed. As a reminder, you should use separate `react-addons-*` packages instead. This only applies if you use the CommonJS builds.
<small>[@gaearon](https://github.com/gaearon) in [#6285](https://github.com/facebook/react/pull/6285)</small>
- Passing `children` to void elements like `<input>` was deprecated, and now throws an error.
<small>[@jonhester](https://github.com/jonhester) in [#3372](https://github.com/facebook/react/pull/3372)</small>
- React-specific properties on DOM `refs` (e.g. `this.refs.div.props`) were deprecated, and are removed now.
<small>[@jimfb](https://github.com/jimfb) in [#5495](https://github.com/facebook/react/pull/5495)</small>
### New deprecations, introduced with a warning
Each of these changes will continue to work as before with a new warning until the release of React 16 so you can upgrade your code gradually.
- `LinkedStateMixin` and `valueLink` are now deprecated due to very low popularity. If you need this, you can use a wrapper component that implements the same behavior: [react-linked-input](https://www.npmjs.com/package/react-linked-input).
<small>[@jimfb](https://github.com/jimfb) in [#6127](https://github.com/facebook/react/pull/6127)</small>
- Future versions of React will treat `<input value={null}>` as a request to clear the input. However, React 0.14 has been ignoring `value={null}`. React 15 warns you on a `null` input value and offers you to clarify your intention. To fix the warning, you may explicitly pass an empty string to clear a controlled input, or pass `undefined` to make the input uncontrolled.
<small>[@antoaravinth](https://github.com/antoaravinth) in [#5048](https://github.com/facebook/react/pull/5048)</small>
- `ReactPerf.printDOM()` was renamed to `ReactPerf.printOperations()`, and `ReactPerf.getMeasurementsSummaryMap()` was renamed to `ReactPerf.getWasted()`.
<small>[@gaearon](https://github.com/gaearon) in [#6287](https://github.com/facebook/react/pull/6287)</small>
### New helpful warnings
- If you use a minified copy of the _development_ build, React DOM kindly encourages you to use the faster production build instead.
<small>[@spicyj](https://github.com/spicyj) in [#5083](https://github.com/facebook/react/pull/5083)</small>
- React DOM: When specifying a unit-less CSS value as a string, a future version will not add `px` automatically. This version now warns in this case (ex: writing `style={{'{{'}}width: '300'}}`. Unitless *number* values like `width: 300` are unchanged.
<small>[@pluma](https://github.com/pluma) in [#5140](https://github.com/facebook/react/pull/5140)</small>
- Synthetic Events will now warn when setting and accessing properties (which will not get cleared appropriately), as well as warn on access after an event has been returned to the pool.
<small>[@kentcdodds](https://github.com/kentcdodds) in [#5940](https://github.com/facebook/react/pull/5940) and [@koba04](https://github.com/koba04) in [#5947](https://github.com/facebook/react/pull/5947)</small>
- Elements will now warn when attempting to read `ref` and `key` from the props.
<small>[@prometheansacrifice](https://github.com/prometheansacrifice) in [#5744](https://github.com/facebook/react/pull/5744)</small>
- React will now warn if you pass a different `props` object to `super()` in the constructor.
<small>[@prometheansacrifice](https://github.com/prometheansacrifice) in [#5346](https://github.com/facebook/react/pull/5346)</small>
- React will now warn if you call `setState()` inside `getChildContext()`.
<small>[@raineroviir](https://github.com/raineroviir) in [#6121](https://github.com/facebook/react/pull/6121)</small>
- React DOM now attempts to warn for mistyped event handlers on DOM elements, such as `onclick` which should be `onClick`.
<small>[@ali](https://github.com/ali) in [#5361](https://github.com/facebook/react/pull/5361)</small>
- React DOM now warns about `NaN` values in `style`.
<small>[@jontewks](https://github.com/jontewks) in [#5811](https://github.com/facebook/react/pull/5811)</small>
- React DOM now warns if you specify both `value` and `defaultValue` for an input.
<small>[@mgmcdermott](https://github.com/mgmcdermott) in [#5823](https://github.com/facebook/react/pull/5823)</small>
- React DOM now warns if an input switches between being controlled and uncontrolled.
<small>[@TheBlasfem](https://github.com/TheBlasfem) in [#5864](https://github.com/facebook/react/pull/5864)</small>
- React DOM now warns if you specify `onFocusIn` or `onFocusOut` handlers as they are unnecessary in React.
<small>[@jontewks](https://github.com/jontewks) in [#6296](https://github.com/facebook/react/pull/6296)</small>
- React now prints a descriptive error message when you pass an invalid callback as the last argument to `ReactDOM.render()`, `this.setState()`, or `this.forceUpdate()`.
<small>[@conorhastings](https://github.com/conorhastings) in [#5193](https://github.com/facebook/react/pull/5193) and [@gaearon](https://github.com/gaearon) in [#6310](https://github.com/facebook/react/pull/6310)</small>
- Add-Ons: `TestUtils.Simulate()` now prints a helpful message if you attempt to use it with shallow rendering.
<small>[@conorhastings](https://github.com/conorhastings) in [#5358](https://github.com/facebook/react/pull/5358)</small>
- PropTypes: `arrayOf()` and `objectOf()` provide better error messages for invalid arguments.
<small>[@chicoxyzzy](https://github.com/chicoxyzzy) in [#5390](https://github.com/facebook/react/pull/5390)</small>
### Notable bug fixes
- Fixed multiple small memory leaks.
<small>[@spicyj](https://github.com/spicyj) in [#4983](https://github.com/facebook/react/pull/4983) and [@victor-homyakov](https://github.com/victor-homyakov) in [#6309](https://github.com/facebook/react/pull/6309)</small>
- Input events are handled more reliably in IE 10 and IE 11; spurious events no longer fire when using a placeholder.
<small>[@jquense](https://github.com/jquense) in [#4051](https://github.com/facebook/react/pull/4051)</small>
- The `componentWillReceiveProps()` lifecycle method is now consistently called when `context` changes.
<small>[@milesj](https://github.com/milesj) in [#5787](https://github.com/facebook/react/pull/5787)</small>
- `React.cloneElement()` doesnt append slash to an existing `key` when used inside `React.Children.map()`.
<small>[@ianobermiller](https://github.com/ianobermiller) in [#5892](https://github.com/facebook/react/pull/5892)</small>
- React DOM now supports the `cite` and `profile` HTML attributes.
<small>[@AprilArcus](https://github.com/AprilArcus) in [#6094](https://github.com/facebook/react/pull/6094) and [@saiichihashimoto](https://github.com/saiichihashimoto) in [#6032](https://github.com/facebook/react/pull/6032)</small>
- React DOM now supports `cssFloat`, `gridRow` and `gridColumn` CSS properties.
<small>[@stevenvachon](https://github.com/stevenvachon) in [#6133](https://github.com/facebook/react/pull/6133) and [@mnordick](https://github.com/mnordick) in [#4779](https://github.com/facebook/react/pull/4779)</small>
- React DOM now correctly handles `borderImageOutset`, `borderImageWidth`, `borderImageSlice`, `floodOpacity`, `strokeDasharray`, and `strokeMiterlimit` as unitless CSS properties.
<small>[@rofrischmann](https://github.com/rofrischmann) in [#6210](https://github.com/facebook/react/pull/6210) and [#6270](https://github.com/facebook/react/pull/6270)</small>
- React DOM now supports the `onAnimationStart`, `onAnimationEnd`, `onAnimationIteration`, `onTransitionEnd`, and `onInvalid` events. Support for `onLoad` has been added to `object` elements.
<small>[@tomduncalf](https://github.com/tomduncalf) in [#5187](https://github.com/facebook/react/pull/5187), [@milesj](https://github.com/milesj) in [#6005](https://github.com/facebook/react/pull/6005), and [@ara4n](https://github.com/ara4n) in [#5781](https://github.com/facebook/react/pull/5781)</small>
- React DOM now defaults to using DOM attributes instead of properties, which fixes a few edge case bugs. Additionally the nullification of values (ex: `href={null}`) now results in the forceful removal, no longer trying to set to the default value used by browsers in the absence of a value.
<small>[@syranide](https://github.com/syranide) in [#1510](https://github.com/facebook/react/pull/1510)</small>
- React DOM does not mistakingly coerce `children` to strings for Web Components.
<small>[@jimfb](https://github.com/jimfb) in [#5093](https://github.com/facebook/react/pull/5093)</small>
- React DOM now correctly normalizes SVG `<use>` events.
<small>[@edmellum](https://github.com/edmellum) in [#5720](https://github.com/facebook/react/pull/5720)</small>
- React DOM does not throw if a `<select>` is unmounted while its `onChange` handler is executing.
<small>[@sambev](https://github.com/sambev) in [#6028](https://github.com/facebook/react/pull/6028)</small>
- React DOM does not throw in Windows 8 apps.
<small>[@Andrew8xx8](https://github.com/Andrew8xx8) in [#6063](https://github.com/facebook/react/pull/6063)</small>
- React DOM does not throw when asynchronously unmounting a child with a `ref`.
<small>[@yiminghe](https://github.com/yiminghe) in [#6095](https://github.com/facebook/react/pull/6095)</small>
- React DOM no longer forces synchronous layout because of scroll position tracking.
<small>[@syranide](https://github.com/syranide) in [#2271](https://github.com/facebook/react/pull/2271)</small>
- `Object.is` is used in a number of places to compare values, which leads to fewer false positives, especially involving `NaN`. In particular, this affects the `shallowCompare` add-on.
<small>[@chicoxyzzy](https://github.com/chicoxyzzy) in [#6132](https://github.com/facebook/react/pull/6132)</small>
- Add-Ons: ReactPerf no longer instruments adding or removing an event listener because they dont really touch the DOM due to event delegation.
<small>[@antoaravinth](https://github.com/antoaravinth) in [#5209](https://github.com/facebook/react/pull/5209)</small>
### Other improvements
- React now uses `loose-envify` instead of `envify` so it installs less transitive dependencies.
<small>[@qerub](https://github.com/qerub) in [#6303](https://github.com/facebook/react/pull/6303)</small>
- Shallow renderer now exposes `getMountedInstance()`.
<small>[@glenjamin](https://github.com/glenjamin) in [#4918](https://github.com/facebook/react/pull/4918)</small>
- Shallow renderer now returns the rendered output from `render()`.
<small>[@simonewebdesign](https://github.com/simonewebdesign) in [#5411](https://github.com/facebook/react/pull/5411)</small>
- React no longer depends on ES5 *shams* for `Object.create` and `Object.freeze` in older environments. It still, however, requires ES5 *shims* in those environments.
<small>[@dgreensp](https://github.com/dgreensp) in [#4959](https://github.com/facebook/react/pull/4959)</small>
- React DOM now allows `data-` attributes with names that start with numbers.
<small>[@nLight](https://github.com/nLight) in [#5216](https://github.com/facebook/react/pull/5216)</small>
- React DOM adds a new `suppressContentEditableWarning` prop for components like [Draft.js](https://facebook.github.io/draft-js/) that intentionally manage `contentEditable` children with React.
<small>[@mxstbr](https://github.com/mxstbr) in [#6112](https://github.com/facebook/react/pull/6112)</small>
- React improves the performance for `createClass()` on complex specs.
<small>[@spicyj](https://github.com/spicyj) in [#5550](https://github.com/facebook/react/pull/5550)</small>

View File

@@ -0,0 +1,34 @@
---
title: "React v15.0.1"
author: zpao
---
Yesterday afternoon we shipped v15.0.0 and quickly got some feedback about a couple of issues. We apologize for these problems and we've been working since then to make sure we get fixes into your hands as quickly as possible.
The first of these issues is related to the removal of an undocumented API. This API was added to enable [JSX Spread Attributes](/react/docs/jsx-spread.html) in our JS compile tools (react-tools, JSXTransformer) before `Object.assign` was standard. When we stopped supporting these tools last year, we kept the API there to catch the longer tail of people using those tools. Meanwhile we moved to using Babel and encouraged others to do the same. Babel will typically compile the spread use to an `_extends` helper, which will use `Object.assign`. We did not properly research other compilation tools before deciding to remove the API in v15. Specifically, TypeScript and coffee-react are two popular packages using `React.__spread`, as well as reactify which still makes use react-tools. In order to make sure that code compiled with these tools is not broken, we will be restoring the `React.__spread` API and adding a warning. It will be removed in the future so if you maintain a project making using of it, we encourage you to compile to `Object.assign` directly or a similar helper function.
The second issue resulted in cursor position being lost in controlled inputs. We merged a pull request earlier this week to fix a separate regression from v0.14. Our goal was to target `<option>` elements but we ended up targeting all interactions with `value` properties. Unfortunately we didn't test it as thoroughly as we thought. We backed out the offending change and fixed the issue in different way which doesn't have the same problem.
We apologize if you installed 15.0.0 and have encountered these issues yourselves.
As usual, you can get install the `react` package via npm or download a browser bundle.
* **React**
Dev build with warnings: <https://fb.me/react-15.0.1.js>
Minified build for production: <https://fb.me/react-15.0.1.min.js>
* **React with Add-Ons**
Dev build with warnings: <https://fb.me/react-with-addons-15.0.1.js>
Minified build for production: <https://fb.me/react-with-addons-15.0.1.min.js>
* **React DOM** (include React in the page before React DOM)
Dev build with warnings: <https://fb.me/react-dom-15.0.1.js>
Minified build for production: <https://fb.me/react-dom-15.0.1.min.js>
## Changelog
### React
- Restore `React.__spread` API to unbreak code compiled with some tools making use of this undocumented API. It is now officially deprecated.
<small>[@zpao](https://github.com/zpao) in [#6444](https://github.com/facebook/react/pull/6444)</small>
### ReactDOM
- Fixed issue resulting in loss of cursor position in controlled inputs.
<small>[@spicyj](https://github.com/spicyj) in [#6449](https://github.com/facebook/react/pull/6449)</small>

View File

@@ -0,0 +1,29 @@
---
id: why-react-ru-RU
title: Почему именно React?
permalink: why-react-ru-RU.html
next: displaying-data-ru-RU.html
---
React — библиотека JavaScript для создания интерфейсов от команд Facebook и Instagram. Многие ассоциируют React с понятием **View** в паттерне **[MVC](https://ru.wikipedia.org/wiki/Model-View-Controller)**.
Мы делали React, чтобы решить одну важную задачу: **создавать действительно большие приложения с постоянно меняющимися данными**.
## Простота
С React вы всегда точно знаете как будет выглядеть ваше приложение, ведь как только изменятся данные, он мгновенно отобразит эти изменения в интерфейсе.
## Декларативность
Как только состояние приложения изменится, React будто нажимает кнопку "обновить" и точно знает, какие части интерфейса надо поменять, а какие нет. Никаких дополнительных инструкций и команд, React сам отслеживает изменения данных и реагирует на них.
## Создание компонентов, как строительных блоков приложения
По сути, разработка на React целиком состоит в создании таких компонентов. С React вы *только* тем и занимаетесь, что пишете новые компоненты, те самые строительные блоки, из которых будет строиться приложение. А поскольку они хорошо инскапсулированы, их удобно использовать повторно даже в других проектах, плюс такой код проще тестировать.
## Уделите этому 5 минут
React бросает вызов многим устоявшимся идеям и правилам, и на первый взгляд, некоторые из его идей выглядят по меньшей мере странными. [Уделите этому 5 минут](https://signalvnoise.com/posts/3124-give-it-five-minutes) пока читаете эту статью; эти безумные идеи нашли свое применение при создании тысяч компонентов не только для Facebook и Instagram, но и в других крупных проектах.
## Узнай больше
Вы можете больше узнать о причинах создания React [отсюда](/react/blog/2013/06/05/why-react.html).

View File

@@ -0,0 +1,29 @@
---
id: why-react-zh-TW
title: Why React?
permalink: why-react-zh-TW.html
next: displaying-data.html
---
React是Facebook和Instagram用來建立使用者介面的JavaScript函式庫. 很多人認為React就是處理 **[MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)**架構中 **V** 的部份.
我們建造React用來解決一個問題: **開發資料能隨時間頻繁更新的大型應用程式**.
## 簡單(Simple)
簡單意味著你所開發的應用程式外觀任何一部分都要能即時呈現, 並且當資料有所變動時React能自動管理所有UI的更新.
## 陳述(Declarative)
當資料改變時, React概念上就像是點擊了 "刷新" 的按鈕, 並且知道只需更新有改變的部份.
## 建立可組合的元件(Composable Components)
React就是在建造可重用的元件(Components). 事實上, 當你使用React時 *唯一* 在做的事就是建立元件(Components). 由於它們封裝性高,元件使得程式碼能夠易於重複使用, 測試, 並且容易做到讓關注點分離(separation of concerns easy).
## 指引(Give It Five Minutes)
React挑戰了許多傳統的觀念, 第一次乍看之下這些構想可能看起來有點瘋狂. [Give it five minutes](https://signalvnoise.com/posts/3124-give-it-five-minutes) 而當閱讀完這篇指引; 這些瘋狂的構想在Facebook和Instagram裡裡外外建立了數以千計的元件(components)之後被證明是可實行的.
## 更多學習資源
從這裡你能學習到更多建造React背後的動機 [this blog post](/react/blog/2013/06/05/why-react.html).

View File

@@ -0,0 +1,124 @@
---
id: displaying-data-ru-RU
title: Отображение данных
permalink: displaying-data-ru-RU.html
prev: why-react-ru-RU.html
next: jsx-in-depth.html
---
Главная задача интерфейса — это отображать данные. React делает это легко и обновляет интерфейс сразу, как только изменятся данные.
## Начало
Давайте рассмотрим простой пример. Создайте файл `hello-react.html` со следующим текстом:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React</title>
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
// ** Ваш код будет здесь! **
</script>
</body>
</html>
```
Добавим в этот шаблон немного JavaScript. Замените комментарий на следующий JSX-код:
```javascript
var HelloWorld = React.createClass({
render: function() {
return (
<p>
Hello, <input type="text" placeholder="Your name here" />!
It is {this.props.date.toTimeString()}
</p>
);
}
});
setInterval(function() {
ReactDOM.render(
<HelloWorld date={new Date()} />,
document.getElementById('example')
);
}, 500);
```
## Реактивные обновления
Откройте `hello-react.html` в браузере и введите в текстовое поле свое имя. Что происходит со страницей? Каждые полсекунды обновляется время, остальные же части страницы остаются без изменений. Обратите внимание, что мы не написали ни строчки кода, чтобы управлять этим поведением. React сам отлично понимает что надо делать и обновляет элементы на странице по мере необходимости.
Суть в том, что React не меняет DOM-дерево до тех пор, пока это не потребуется. **Чтобы отразить изменения, React использует быстрое внутреннее представление DOM-дерева и просчитывает как его изменить наиболее эффективно**.
Передаваемые в компонент данные называются `props` — сокращенно от "properties". В JSX коде они передаются как атрибуты компонента. Считайте, что компонент получает `props` только для чтения. **Никогда не перезаписывайте значения `this.props` внутри компонента.**
## Компоненты как функции
Компоненты React — довольно простые сущности. Можно считать их обыкновенными функциями, которые принимают на входе `props` и `state` (см. далее) и возвращают HTML. Если помнить об этом, то компоненты становятся простыми для понимания.
> Замечание:
>
> **Есть одно ограничение**: Компоненты React умеют возвращать только один узел. Если вам надо вернуть сразу несколько, они *должны* быть обернуты в один корневой узел.
## Синтаксис JSX
Мы убеждены, что компоненты — самый подходящий способ разделения ответственностей, гораздо более удобный чем "шаблоны" и "вынесение логики на страницу". Мы считаем, что разметка и код, который её генерирует, неотделимы друг от друга. Плюс, логика на странице часто бывает запутанной, и использование шаблонизаторов, чтобы описать её, только затрудняет работу.
Мы решили, что лучшим вариантом будет генерировать HTML и деревья компонентов прямо из JS кода. Так вы сможете зайдействовать всю выразительную мощь современного языка программирования для создания интерфейсов.
А чтобы упростить создание узлов дерева, мы ввели **опциональный** HTML-подобный синтаксис.
**JSX позволяет вам создавать JavaScript объекты используя синтаксис HTML**. Для генерации ссылки в React вы напишете на чистом JavaScript:
`React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')`
С JSX это станет:
`<a href="https://facebook.github.io/react/">Hello!</a>`
Мы установили, что с JSX создавать React приложения проще, и дизайнеров как правило устраивает его синтаксис. Но у разных людей разные предпочтения, поэтому стоит сказать, что **JSX необязателен при работе с React.**
JSX сам по себе очень прост. Чтобы узнать о нем больше, почитайте [подробно про JSX](/react/docs/jsx-in-depth.html). Или можете попробовать его в [Babel REPL](https://babeljs.io/repl/).
JSX похож на HTML, но но имеет существенные отличия. Почитайте про [подводные камни JSX](/react/docs/jsx-gotchas.html), чтобы понять их ключевые различия.
[Babel предлагает несколько способов начать работу с JSX](http://babeljs.io/docs/setup/), от консольных утилит до интеграций с Ruby on Rails. Выберите тот инструмент, который лучше всего вам подходит.
## React без использования JSX
JSX полностью опционален; вам совсем необязательно использовать его вместе с React. Вы можете создавать React-элементы на чистом JavaScript используя функцию `React.createElement`, которая принимает имя тега или компонента, объект со свойствами, и набор необязательных дочерних элементов.
```javascript
var child1 = React.createElement('li', null, 'First Text Content');
var child2 = React.createElement('li', null, 'Second Text Content');
var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
ReactDOM.render(root, document.getElementById('example'));
```
Для удобства, вы можете создать сокращенные фабричные функции, чтобы создавать React-элементы из ваших собственных компонентов.
```javascript
var Factory = React.createFactory(ComponentClass);
...
var root = Factory({ custom: 'prop' });
ReactDOM.render(root, document.getElementById('example'));
```
А для базовых HTML тегов в React уже есть встроенные фабрики:
```javascript
var root = React.DOM.ul({ className: 'my-list' },
React.DOM.li(null, 'Text Content')
);
```

View File

@@ -40,10 +40,10 @@ A safer alternative is to find the [unicode number corresponding to the entity](
<div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
```
You can use mixed arrays with strings and JSX elements.
You can use mixed arrays with strings and JSX elements. Each JSX element in the array needs a unique key.
```javascript
<div>{['First ', <span>&middot;</span>, ' Second']}</div>
<div>{['First ', <span key="middot">&middot;</span>, ' Second']}</div>
```
As a last resort, you always have the ability to [insert raw HTML](/react/tips/dangerously-set-inner-html.html).

View File

@@ -0,0 +1,78 @@
---
id: interactivity-and-dynamic-uis-ru-RU
title: Интерактивные и динамические интерфейсы
permalink: interactivity-and-dynamic-uis-ru-RU.html
prev: jsx-gotchas.html
next: multiple-components.html
---
Вы уже знаете [как показывать данные](/react/docs/displaying-data.html) с React. Теперь давайте добавим в наши интферфейсы немного интерактивности.
## Простой пример
```javascript
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
```
## Обработка событий и синтетические события
С React вы просто передаете функцию-обработчик нужного события как аргумент, почти так же, как делали это в HTML. Благодаря механизму синтетических событий React гарантирует, что все события будут вести себя одинаково во всех браузерах. Другими словами, React знает, как работает всплытие и перехват событий по спецификации. События, которые он передает в ваши обработчики, будут соответствовать [спецификации W3C](http://www.w3.org/TR/DOM-Level-3-Events/), несмотря на то, каким браузером вы пользуетесь.
## Как это работает: автоматическое связывание и делегирование событий
Чтобы ваш код был не только понятным, но и быстрым, React делает следующее:
**Автоматическое связывание:** Когда в JavaScript создаются функции обратного вызова, вам надо привязать метод к тому объекту, на котором он будет вызываться, чтобы значение `this` было корректным. С React привязка метода к компоненту происходит автоматически ([кроме тех случаев, когда вы используете классы ES6](/react/docs/reusable-components.html#no-autobinding)). И делается это с минимальной нагрузкой на процессор и память.
**Делегирование событий:** На самом же деле, React добавляет обработчики событий не к узлам дерева. Сразу после запуска, React начинает прослушивать все события с самого верхнего уровня, используя единый слушатель. Когда добавляется новый компонент или удаляется старый, обработчики событий просто добавляются или удаляются из памяти React. И когда событие наступает, React уже заранее знает какому из обработчиков его передать. Когда в памяти больше не остается обработчиков, React перестает обрабатывать события. Если хотите узнать о том, почему эта механика так быстро работает, почитайте [отличный пост в блоге David Walsh](http://davidwalsh.name/event-delegate).
## Компоненты как конечные автоматы
React считает интерфейсы обыкновенными конечными автоматами. Работать с интерфейсом становится проще, если представлять его как конечный автомат, который меняет состояния и отрисовывает их.
В React вы просто обновляете состояние компонента, а потом выводите новый интерфейс уже с новыми данными. Все изменения в DOM-дереве React сделает сам, причем наиболее эффективным способом.
## Как работает состояние
Чтобы сообщить React о том, что данные изменились, вы вызываете метод `setState(data, callback)`. В этом методе происходит обновление состояния `this.state` новыми данными из `data`, и компонент отрисуется заново. После этого вызывается функция `callback`. Но вы редко будете ей пользоваться, ведь React сам обновляет интерфейс.
## В каких компонентах хранить состояние?
Большинство компонентов должны просто брать данные из `props` и отрисовывать их. Но иногда вам надо реагировать на действия пользователя, делать запросы на сервер или просто сделать что-то по таймеру. В таких случаях используйте состояние.
**Старайтесь делать компоненты без состояния.** Следуя этому правилу, вы будете выносить работу с состоянием с уровня представления в другие, более подходящие места. Тем самым, вы снизите сложность приложения, упрощая его понимание.
Основной принцип такой: создаются несколько компонентов без состояния, которые формируют дерево. Они будут заниматься только отрисовкой данных. А все данные для них будут у родительского компонента, который будет на вершине этого дерева компонентов. Он и будет передавать данные дочерним узлам через `props`. Этот компонент с общим состоянием содержит в себе всю логику взаимодействия, а дочерние компоненты будут только отрисовывать данные, которые будут у них в `props`.
## Какие данные *надо* помещать в состояние?
**Состояние должно содержать данные, которые нужны для обновления интерфейса.** В реальных приложениях такие данные, как правило, незначительны по объему, и могут быть сериализованы в JSON. Когда вы создаете компонент с состоянием, старайтесь поместить в него минимум данных. А уже внутри метода `render()` вычисляйте остальные данные, используя значения из состояния.
Со временем вы увидите, что такой подход позволяет создавать более стройные и устойчивые к изменениям приложения. Добавление в состояние лишних данных требует от вас дополнительных затрат на их синхронизацию. Но этого можно избежать, если позволить React делать все эти вычисления за вас.
## Какие данные *не надо* помещать в состояние?
Состояние `this.state` должно содержать минимум данных, необходимых для отображения интерфейса. Поэтому не стоит хранить в нем:
* **Вычисляемые данные:** Не волнуйтесь о данных, которые можно вычислить из состояния. Согласованность данных проще обеспечить, если производить все вычисления в методе `render()`. Например, если в состоянии хранится список элементов, и вам надо вывести его размер в виде строки, напишите `this.state.listItems.length + ' элементов'` в методе `render()`. Это будет правильнее, чем хранить размер списка в состоянии.
* **Компоненты React:** Создавайте их в методе `render()`, опираясь на данные из `props` и `state`.
* **Значения, повторяющие `props`:** Старайтесь по мере возможности использовать `props` как единственный источник данных. Хранить значения `props` в состоянии допускается, только если вам надо где-то хранить их прошлые значения, ведь `props` могут измениться после отрисовки родительского компонента.

View File

@@ -299,4 +299,8 @@ However, you may still specify `.propTypes` and `.defaultProps` by setting them
>
> Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component. Normally this isn't an issue, since stateless functions do not provide an imperative API. Without an imperative API, there isn't much you could do with an instance anyway. However, if a user wants to find the DOM node of a stateless function component, they must wrap the component in a stateful component (eg. ES6 class component) and attach the ref to the stateful wrapper component.
> NOTE:
>
> In React v0.14, stateless functional components were not permitted to return `null` or `false` (a workaround is to return a `<noscript />` instead). This was fixed in React v15, and stateless functional components are now permitted to return `null`.
In an ideal world, most of your components would be stateless functions because in the future well also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.

View File

@@ -166,3 +166,8 @@ To make an uncontrolled component, `defaultValue` is used instead.
> Note:
>
> You can pass an array into the `value` attribute, allowing you to select multiple options in a `select` tag: `<select multiple={true} value={['B', 'C']}>`.
### Imperative operations
If you need to imperatively perform an operation, you have to obtain a [reference to the DOM node](/react/docs/more-about-refs.html#the-ref-callback-attribute).
For instance, if you want to imperatively submit a form, one approach would be to attach a `ref` to the `form` element and manually call `form.submit()`.

View File

@@ -64,7 +64,7 @@ or using an ES6 arrow function:
When attaching a ref to a DOM component like `<div />`, you get the DOM node back; when attaching a ref to a composite component like `<TextInput />`, you'll get the React class instance. In the latter case, you can call methods on that component if any are exposed in its class definition.
Note that when the referenced component is unmounted and whenever the ref changes, the old ref will be called with `null` as an argument. This prevents memory leaks in the case that the instance is stored, as in the first example. Also note that when writing refs with inline function expressions as in the examples here, React sees a different function object each time so on every update, ref will be called with `null` immediately before it's called with the component instance.
Note that when the referenced component is unmounted and whenever the ref changes, the old ref will be called with `null` as an argument. This prevents memory leaks in the case that the instance is stored, as in the second example. Also note that when writing refs with inline function expressions as in the examples here, React sees a different function object each time so on every update, ref will be called with `null` immediately before it's called with the component instance.
## The ref String Attribute

View File

@@ -3,78 +3,11 @@ id: tooling-integration
title: Tooling Integration
permalink: tooling-integration.html
prev: more-about-refs.html
next: addons.html
next: language-tooling.html
---
Every project uses a different system for building and deploying JavaScript. We've tried to make React as environment-agnostic as possible.
We've tried to make React as environment-agnostic as possible. People use React in a variety of languages (JavaScript, TypeScript, ClojureScript, etc) and in a variety of environments (web, iOS, Android, NodeJS, Nashorn, etc). There are many tools to help you build great applications. In these sections we introduce some of the tools that are most commonly used together with React.
## React
### CDN-hosted React
We provide CDN-hosted versions of React [on our download page](/react/downloads.html). These pre-built 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, Babel 5 provided an in-browser ES6 and JSX transformer for development called browser.js that can be included from [CDNJS](http://cdnjs.com/libraries/babel-core/5.8.34). Include a `<script type="text/babel">` tag to engage the JSX transformer.
> 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](https://www.npmjs.com/), you can run `npm install -g babel-cli`. Babel has built-in support for React v0.12+. Tags are automatically transformed to their equivalent `React.createElement(...)`, `displayName` is automatically inferred and added to all `React.createClass` calls.
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: `babel --watch src/ --out-dir lib/`.
Beginning with Babel 6, there are no transforms included by default. This means that options must be specified when running the `babel` command, or a `.babelrc` must specify options. Additional packages must also be installed which bundle together a number of transforms, called presets. The most common use when working with React will be to include the `es2015` and `react` presets. More information about the changes to Babel can be found in [their blog post announcing Babel 6](http://babeljs.io/blog/2015/10/29/6.0.0/).
Here is an example of what you will do if using ES2015 syntax and React:
```
npm install babel-preset-es2015 babel-preset-react
babel --presets es2015,react --watch src/ --out-dir lib/
```
By default JSX files with a `.js` extension are transformed. Run `babel --help` for more information on how to use Babel.
Example output:
```
$ cat test.jsx
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
ReactDOM.render(<HelloMessage name="John" />, mountNode);
$ babel test.jsx
"use strict";
var HelloMessage = React.createClass({
displayName: "HelloMessage",
render: function render() {
return React.createElement(
"div",
null,
"Hello ",
this.props.name
);
}
});
ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
```
### Helpful Open-Source Projects
The open-source community has built tools that integrate JSX with several editors and build systems. See [JSX integrations](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations) for the full list.
* [Language Tooling](/react/docs/language-tooling.html) describes how to set up tools like Babel to transpile JSX for a better development experience.
* [Package Management](/react/docs/package-management.html) describes how to configure React as a dependency of your project.
* [Server-side Environments](/react/docs/environments.html) describes how to configure your environment for server-side rendering with React.

View File

@@ -0,0 +1,79 @@
---
id: language-tooling
title: Language Tooling
permalink: language-tooling.html
prev: tooling-integration.html
next: package-management.html
---
## ES2015 with JSX
### In-browser JSX Transform
If you like using JSX, Babel 5 provided an in-browser ES2015 and JSX transformer for development called browser.js that can be included from [CDNJS](https://cdnjs.com/libraries/babel-core/5.8.34). Include a `<script type="text/babel">` tag to engage the JSX transformer.
> 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](https://www.npmjs.com/), you can run `npm install -g babel-cli`. Babel has built-in support for React v0.12+. Tags are automatically transformed to their equivalent `React.createElement(...)`, `displayName` is automatically inferred and added to all `React.createClass` calls.
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: `babel --watch src/ --out-dir lib/`.
Beginning with Babel 6, there are no transforms included by default. This means that options must be specified when running the `babel` command, or a `.babelrc` must specify options. Additional packages must also be installed which bundle together a number of transforms, called presets. The most common use when working with React will be to include the `es2015` and `react` presets. More information about the changes to Babel can be found in [their blog post announcing Babel 6](http://babeljs.io/blog/2015/10/29/6.0.0).
Here is an example of what you will do if using ES2015 syntax and React:
```
npm install babel-preset-es2015 babel-preset-react
babel --presets es2015,react --watch src/ --out-dir lib/
```
By default JSX files with a `.js` extension are transformed. Run `babel --help` for more information on how to use Babel.
Example output:
```
$ cat test.js
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
ReactDOM.render(<HelloMessage name="John" />, mountNode);
$ babel test.js
"use strict";
var HelloMessage = React.createClass({
displayName: "HelloMessage",
render: function render() {
return React.createElement(
"div",
null,
"Hello ",
this.props.name
);
}
});
ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
```
### Helpful Open-Source Projects
The open-source community has built tools that integrate JSX with several editors and build systems. See [JSX integrations](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations) for the full list.
## Flow
Flow is a JavaScript type checker released by Facebook, and it supports JSX. For more info, checkout the [Flow homepage](http://flowtype.org/).
## TypeScript
Microsoft TypeScript now supports JSX. For more info, check out the [TypeScript JSX Documentation](http://www.typescriptlang.org/docs/handbook/jsx.html) or their guide on [getting started with react+webpack](https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/tutorials/React%20%26%20Webpack.md).

View File

@@ -0,0 +1,126 @@
---
id: package-management
title: Package Management
permalink: package-management.html
prev: language-tooling.html
next: environments.html
---
## CDN-hosted React
We provide CDN-hosted versions of React [on our download page](/react/downloads.html). These pre-built files use the UMD module format. Dropping them in with a simple `<script>` tag will inject the `React` and `ReactDOM` globals into your environment. It should also work out-of-the-box in CommonJS and AMD environments.
## Using React from npm
You can use React with a CommonJS module system like [browserify](http://browserify.org/) or [webpack](https://webpack.github.io/). Use the [`react`](https://www.npmjs.com/package/react) and [`react-dom`](https://www.npmjs.com/package/react-dom) npm packages.
```js
// main.js
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
```
Configure [babel](https://babeljs.io/) with a `.babelrc` file:
```json
{ "presets": ["react"] }
```
> Note:
>
> If you are using ES2015, you will want to also use the `babel-preset-es2015` package.
To install React DOM and build your bundle with browserify:
```sh
$ npm install --save react react-dom babelify babel-preset-react
$ browserify -t [ babelify ] main.js -o bundle.js
```
To install React DOM and build your bundle with webpack:
```sh
$ npm install --save react react-dom babel-preset-react babel-loader babel-core
$ webpack main.js bundle.js --module-bind 'js=babel-loader'
```
> Note:
>
> If you are using ES2015, you will want to also use the `babel-preset-es2015` package.
**Note:** by default, React will be in development mode, which is slower, and not advised for production. To use React in production mode, set the environment variable `NODE_ENV` to `production` (using envify or webpack's DefinePlugin). For example:
```js
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify("production")
}
});
```
Update your HTML file as below:
```html{8,12}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<!-- No need for Babel! -->
</head>
<body>
<div id="example"></div>
<script src="build/helloworld.js"></script>
</body>
</html>
```
## Using React from Bower
Bower is a package manager optimized for the front-end development. If multiple packages depend on a package - jQuery for example - Bower will download jQuery just once. This is known as a flat dependency graph and it helps reduce page load. For more info, visit http://bower.io/
If you'd like to use bower, it's as easy as:
```
bower install --save react
```
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="bower_components/react/react.js"></script>
<script src="bower_components/react/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
```
## Using master
We have instructions for building from `master` [in our GitHub repository](https://github.com/facebook/react).

View File

@@ -0,0 +1,75 @@
---
id: environments
title: Server-side Environments
permalink: environments.html
prev: package-management.html
next: addons.html
---
One of the great things about React is that it doesn't require the DOM as a dependency, which means it is possible to render a React application on the server and send the HTML markup down to the client. There are a few things that React expects, so this guide will help you get started in your preferred environment.
## Node.js
[Node.js](http://nodejs.org/) is a popular JavaScript runtime that comes with an extensive core library and support for installing packages from npm to expand on the basic functionality. As we've described elsewhere in the documentation, you can install `react` and `react-dom` from npm.
Example:
```js
var React = require('react');
var ReactDOMServer = require('react-dom/server');
var element = React.createElement('div', null, 'Hello World!');
console.log(ReactDOMServer.renderToString(element));
```
If you use JSX, you may want to pre-compile your components. Alternatively you may want to consider using [Babel's require hook](https://babeljs.io/docs/usage/require/) or [`babel-node`](https://babeljs.io/docs/usage/cli/#babel-node).
> Note:
>
> Some versions of Node.js have an `Object.assign` implementation that does not preserve key order. This can cause errors when validating the markup, creating a warning that says "React attempted to reuse markup in a container but the checksum was invalid". If you run into this issue, you can override `Object.assign` to use a polyfill that preserves key order. For more details, see [Issue #6451](https://github.com/facebook/react/issues/6451).
## Nashorn
Nashorn is a lightweight high-performance JavaScript runtime that runs within the JVM. React should run out of the box in Java 8+.
Example:
```java
import java.io.IOException;
import java.io.InputStream;
import java.io.FileReader;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ReactRender
{
public static void main(String[] args) throws ScriptException, IOException {
ScriptEngine nashorn = new ScriptEngineManager().getEngineByName("nashorn");
// These files can be downloaded as a part of the starter kit
// from https://facebook.github.io/react
nashorn.eval(new FileReader("path/to/react.js"));
nashorn.eval(new FileReader("path/to/react-dom-server.js"));
System.out.println(nashorn.eval(
"ReactDOMServer.renderToString(" +
"React.createElement('div', null, 'Hello World!')" +
");"
));
}
}
```
If your application uses npm packages, or you want to transform JSX in Nashorn, you will need to do some additional environment setup. The following resources may be helpful in getting you started:
* [http://winterbe.com/posts/2015/02/16/isomorphic-react-webapps-on-the-jvm/](http://winterbe.com/posts/2015/02/16/isomorphic-react-webapps-on-the-jvm/)
* [https://github.com/nodyn/jvm-npm](https://github.com/nodyn/jvm-npm)
* [https://gist.github.com/aesteve/883e0fd33390451cb8eb](https://gist.github.com/aesteve/883e0fd33390451cb8eb)
> Note:
>
> Using Babel within Nashorn will require Java 8u72+, as update 72 fixed [JDK-8135190](https://bugs.openjdk.java.net/browse/JDK-8135190).

View File

@@ -2,7 +2,7 @@
id: addons
title: Add-ons
permalink: addons.html
prev: tooling-integration.html
prev: environments.html
next: animation.html
---

View File

@@ -12,6 +12,10 @@ next: clone-with-props.html
var ReactTestUtils = require('react-addons-test-utils');
```
> Note:
>
> Airbnb has released a testing utility called Enzyme, which makes it easy to assert, manipulate, and traverse your React Components' output. If you're deciding on a unit testing library, it's worth checking out: [http://airbnb.io/enzyme/](http://airbnb.io/enzyme/)
### Simulate
```javascript
@@ -138,7 +142,8 @@ Traverse all components in `tree` and accumulate all components where `test(comp
```javascript
array scryRenderedDOMComponentsWithClass(
ReactComponent tree, string className
ReactComponent tree,
string className
)
```
@@ -192,7 +197,8 @@ Finds all instances of components with type equal to `componentClass`.
```javascript
ReactComponent findRenderedComponentWithType(
ReactComponent tree, function componentClass
ReactComponent tree,
function componentClass
)
```

View File

@@ -179,10 +179,10 @@ var MediaQuery = React.createClass({
var checkMediaQuery = function(){
var type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';
if (type !== this.state.type){
this.setState({type:type});
this.setState({type:type});
}
};
window.addEventListener('resize', checkMediaQuery);
checkMediaQuery();
},

View File

@@ -5,21 +5,21 @@ permalink: context-zh-CN.html
prev: advanced-performance-zh-CN.html
---
React最大的优势之一是很容易从你的React组件里跟踪数据流动。当你看一个组件,你可以很容易准确看出哪个props被传入这让你的APP很容易推断。
React优势之一是你可以很容易地从React组件里跟踪数据流动。当你看一个组件,你可以很容易地判断出传入了哪些props而这也有利于你的App进行逻辑推断。
偶尔,你想通过组件树传递数据而不在每一级上手工下传propReact的 "context" 让你做到这点。
有时,你想通过在每一级组件设置prop的方式来向组件树内传递数据。那么React的"context"特性可以让你做到这点。
 注意:
 
 Context是一个先进的实验性特性这个 API 很可能在未来版本变化.
> 注意:
>
> 大多数应用将不会需要用到 context. 尤其是如果你刚开始用React,你很可能不会想用 context.使用 context 将会使你的代码很难理解因为它让数据流不清晰.它类似于在你的应用里使用全局变量传递state.
> Context是一个先进的实验性特性这个API很可能在未来版本变化。
>
> **如果你必须使用 context ,保守的使用它**
> 大多数应用将不会需要用到context。尤其是如果你刚开始用React你很可能不会想用它。使用context将会使你的代码难以理解因为它让数据流变得不清晰。它类似于在你的应用里用以传递state的全局变量。
>
> 不论你正在创建一个应用或者是库,试着分离你对 context 的使用到一个小区域,并尽可能避免直接使用 context API,以便在API变动时容易升级.
> **如果你必须使用context请保守地使用它。**
>
> 不论你正在创建一个应用或者是库试着缩小context的使用范围并尽可能避免直接使用context相关API以便在API变动时容易升级。
## 从树里自动传递info
## 在组件树内自动传递info
假设你有一个这样的结构:
@@ -55,7 +55,7 @@ var MessageList = React.createClass({
});
```
在这例子里,我们手工穿透一个 `color` prop 以便于恰当格式化 `Button``Message` 组件.主题是一个很好的例子,当你可能想整个子树都可以访问一部分信息时(比如color). 使用 context 我们可以自动传过这个树:
在这例子里我们手工传递一个`color`prop以便于`Button``Message`组件添加合适的样式。当你想所有子组件可以访问一部分信息时(比如color),上面的设置主题是一个很好的例子。通过使用context我们能自动在组件树中传递信息:
```javascript{2-4,7,18,25-30,33}
var Button = React.createClass({
@@ -97,13 +97,13 @@ var MessageList = React.createClass({
});
```
通过添加 `childContextTypes``getChildContext` 到 `MessageList` ( context 提供),React下传信息子树中的任何组件(在这个例子中, `Button`可以由定义 `contextTypes`来访问它).
通过添加`childContextTypes``getChildContext`到 `MessageList`(context提供者)React会自动下传信息,并且通过定义`contextTypes`子树中的任何组件(在这个例子中,子组件是`Button`)可以访问`context`。
如果 `contextTypes` 没有定义,那么 `this.context` 将是一个空对象.
如果`contextTypes`没有定义那么`this.context`将是一个空对象
## 父子耦合
Context 同样可以使你构建这样的 APT:
Context同样可以使你构建这样的API:
```javascript
<Menu>
@@ -113,19 +113,19 @@ Context 同样可以使你构建这样的 APT:
</Menu>
```
通过在 `Menu` 组件下传相关的信息,每个 `MenuItem` 可以与包含他们的 `Menu` 组件沟通.
通过在`Menu`组件下传相关的信息每个`MenuItem` 可以与包含他们的`Menu`组件沟通
**在你用这个API构建组件以前,考虑一下是否有清晰的替代方案** 我们 喜欢像这样简单的用数组传递items:
**在你用这个API构建组件以前考虑一下是否有清晰的替代方案** 我们喜欢用数组传递items,就像下面这样:
```javascript
<Menu items={['aubergine', 'butternut squash', 'clementine']} />
```
记住你同样可以在props里传递整个React组件,如果你想.
记住,如果你愿意,你同样可以在props里传递整个React组件
## 在生命周期方法里引用 context
## 在生命周期方法里引用context
如果 `contextTypes` 在一个组件中定义,接下来的生命周期方法会收到一个额外的参数, `context` 对象:
如果`contextTypes`是定义在一个组件中接下来的生命周期方法会收到一个额外的参数`context`对象
```javascript
void componentWillReceiveProps(
@@ -147,7 +147,7 @@ void componentDidUpdate(
## 在无状态函数组件里引用 context
无状态函数同样能够引用 `context` 如果 `contextTypes` 被定义为函数的属性.下面的代码展示了被写为无状态函数组件的 `Button` 组件.
如果 `contextTypes` 被定义为函数的属性,无状态函数同样能够引用`context`。下面的代码展示了被写为无状态函数组件的`Button`组件
```javascript
function Button(props, context) {
@@ -160,9 +160,9 @@ function Button(props, context) {
Button.contextTypes = {color: React.PropTypes.string};
```
## Updating context
## 更新context
state 或者 props 变化时 `getChildContext` 函数会被调用。为了更新context的数据,用 `this.setState` 触发一个本地的state更新。这将会触发一个新的 context 并且子级将收到变化。
当stateprops改变时,会调用`getChildContext`方法。为了更新context的数据,需要使用`this.setState`触发组件state更新。这将会触发一个新的context并且子组件也能接收变化。
```javascript
var MediaQuery = React.createClass({
@@ -179,10 +179,10 @@ var MediaQuery = React.createClass({
var checkMediaQuery = function(){
var type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';
if (type !== this.state.type){
this.setState({type:type});
this.setState({type:type});
}
};
window.addEventListener('resize', checkMediaQuery);
checkMediaQuery();
},
@@ -194,12 +194,12 @@ var MediaQuery = React.createClass({
## 什么时候不用 context
像全局变量是在写清晰代码时最好要避免的,你应该在大多数情况下避免使用context. 特别是,在用它来"节省输入"和代替显传入props时要三思.
在写清晰代码时最好要避免使用全局变量一样,在大多数情况下,你应该避免使用context特别是在用它来"节省输入"和代替显传入props时要三思
context最好的使用场景是隐式传入登录的用户,当前的语言,或者主题信息.要不然所有这些可能就是全局变量,但是context让你限定他们到一个单独的React树里.
隐式传入登录的用户当前的语言或者主题信息是context最好的使用场景。要不然所有这些可能就是全局变量但是context让你限定他们到一个单独的React树里
不要用context在组件里传递你的模型数据.通过树显示的传递你的数据更容易理解.使用context使你的组件耦合和不可复用,因为 依赖于他们在哪里渲染,他们会表现不同的行为.
在组件里传递你的模型数据时,不要依赖context在组件树内显式传递数据,会更容易令人理解。之所以使用context会增加组件耦合度以及降低复用性,是因为组件在不同的地方渲染时,他们会表现不同的行为
## 已知的限制
如果一个由组件提供的context值变动,使用那个值的子级不会更新,如果一个直接的父级从 `shouldComponentUpdate` 返回 `false` .详见 issue [#2517](https://github.com/facebook/react/issues/2517) .
假设由父组件提供的context值发生变动,但中间父级组件的`shouldComponentUpdate`返回`false`那么后代子级不会更新context。详见 issue [#2517](https://github.com/facebook/react/issues/2517)

View File

@@ -7,28 +7,38 @@ next: videos.html
---
### React.js Conf 2015
January 28 & 29
January 28 & 29 in Facebook HQ, CA
[Website](http://conf2015.reactjs.org/) - [Schedule](http://conf2015.reactjs.org/schedule.html) - [Videos](https://www.youtube.com/playlist?list=PLb0IAmt7-GS1cbw4qonlQztYV1TAW0sCr)
<iframe width="650" height="315" src="//www.youtube-nocookie.com/embed/KVZ-P-ZI6W4?list=PLb0IAmt7-GS1cbw4qonlQztYV1TAW0sCr" frameborder="0" allowfullscreen></iframe>
### ReactEurope 2015
July 2 & 3
July 2 & 3 in Paris, France
[Website](http://www.react-europe.org/) - [Schedule](http://www.react-europe.org/#schedule)
### Reactive 2015
November 2-4
November 2-4 in Bratislava, Slovakia
[Website](https://reactive2015.com/) - [Schedule](https://reactive2015.com/schedule_speakers.html#schedule)
### React.js Conf 2016
February 22 & 23
February 22 & 23 in San Francisco, CA
[Website](http://conf.reactjs.com/) - [Schedule](http://conf.reactjs.com/schedule.html) - [Videos](https://www.youtube.com/playlist?list=PLb0IAmt7-GS0M8Q95RIc2lOM6nc77q1IY)
### ReactEurope 2016
June 2 & 3
June 2 & 3 in Paris, France
[Website](http://www.react-europe.org/) - [Schedule](http://www.react-europe.org/#schedule)
### ReactRally 2016
August 25-26 in Salt Lake City, UT
[Website](http://www.reactrally.com/) - [Schedule](http://www.reactrally.com/#/schedule)
### Reactive 2016
October 26-28 in Bratislava, Slovakia
[Website](https://reactiveconf.com/)

View File

@@ -12,52 +12,10 @@ The easiest way to start hacking on React is using the following JSFiddle Hello
* **[React JSFiddle](https://jsfiddle.net/reactjs/69z2wepo/)**
* [React JSFiddle without JSX](https://jsfiddle.net/reactjs/5vjqabv3/)
## Using React from npm
We recommend using React with a CommonJS module system like [browserify](http://browserify.org/) or [webpack](https://webpack.github.io/). Use the [`react`](https://www.npmjs.com/package/react) and [`react-dom`](https://www.npmjs.com/package/react-dom) npm packages.
## Starter Pack
```js
// main.js
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
```
To install React DOM and build your bundle with browserify:
```sh
$ npm install --save react react-dom babelify babel-preset-react
$ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
```
To install React DOM and build your bundle with webpack:
```sh
$ npm install --save react react-dom babel-preset-react
$ webpack
```
> Note:
>
> If you are using ES2015, you will want to also use the `babel-preset-es2015` package.
**Note:** by default, React will be in development mode, which is slower, and not advised for production. To use React in production mode, set the environment variable `NODE_ENV` to `production` (using envify or webpack's DefinePlugin). For example:
```js
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify("production")
}
});
```
## Quick Start Without npm
If you're not ready to use npm yet, you can download the starter kit which includes prebuilt copies of React and React DOM.
If you're just getting started, you can download the starter kit. The starter kit includes prebuilt copies of React and React DOM for the browser, as well as a collection of usage examples to help you get started.
<div class="buttons-unit downloads">
<a href="/react/downloads/react-{{site.react_version}}.zip" class="button">
@@ -110,58 +68,12 @@ Then reference it from `helloworld.html`:
Note that some browsers (Chrome, e.g.) will fail to load the file unless it's served via HTTP.
### Offline Transform
## Using React with npm or Bower
First install the [Babel](http://babeljs.io/) command-line tools (requires [npm](https://www.npmjs.com/)):
```
npm install --global babel-cli
npm install babel-preset-react
```
Then, translate your `src/helloworld.js` file to plain JavaScript:
```
babel --presets react src --watch --out-dir build
```
> Note:
>
> If you are using ES2015, you will want to also use the `babel-preset-es2015` package.
The file `build/helloworld.js` is autogenerated whenever you make a change. Read the [Babel CLI documentation](http://babeljs.io/docs/usage/cli/) for more advanced usage.
```javascript{2}
ReactDOM.render(
React.createElement('h1', null, 'Hello, world!'),
document.getElementById('example')
);
```
Update your HTML file as below:
```html{8,12}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<!-- No need for Babel! -->
</head>
<body>
<div id="example"></div>
<script src="build/helloworld.js"></script>
</body>
</html>
```
You can also use React with package managers like npm or Bower. You can learn more in our [Package Managers](/react/docs/package-management.html) section.
## Next Steps
Check out [the tutorial](/react/docs/tutorial.html) and the other examples in the starter kit's `examples` directory to learn more.
We also have a wiki where the community contributes with [workflows, UI-components, routing, data management etc.](https://github.com/facebook/react/wiki/Complementary-Tools)
Good luck, and welcome!

View File

@@ -98,7 +98,7 @@ Verifies the object is a ReactElement.
array React.Children.map(object children, function fn [, object thisArg])
```
Invoke `fn` on every immediate child contained within `children` with `this` set to `thisArg`. If `children` is a nested object or array it will be traversed: `fn` will never be passed the container objects. If children is `null` or `undefined` returns `null` or `undefined` rather than an array.
Invoke `fn` on every immediate child contained within `children` with `this` set to `thisArg`. If `children` is a [keyed fragment](/react/docs/create-fragment.html) or array it will be traversed: `fn` will never be passed the container objects. If children is `null` or `undefined` returns `null` or `undefined` rather than an array.
#### React.Children.forEach
@@ -139,7 +139,7 @@ The `react-dom` package provides DOM-specific methods that can be used at the to
### ReactDOM.render
```javascript
ReactComponent render(
render(
ReactElement element,
DOMElement container,
[function callback]
@@ -161,6 +161,10 @@ If the optional callback is provided, it will be executed after the component is
> `ReactDOM.render()` does not modify the container node (only modifies the children of the container). In
> the future, it may be possible to insert a component to an existing DOM node without overwriting
> the existing children.
>
> `ReactDOM.render()` currently returns a reference to the root `ReactComponent` instance. However, using this return value is legacy
> and should be avoided because future versions of React may render components asynchronously in some cases. If you need a reference to the root `ReactComponent` instance, the preferred solution is to attach a
> [callback ref](/react/docs/more-about-refs.html#the-ref-callback-attribute) to the root element.
### ReactDOM.unmountComponentAtNode

View File

@@ -0,0 +1,56 @@
---
id: webcomponents-zh-CN
title: Web Components
permalink: webcomponents-zh-CN.html
prev: reconciliation-zh-CN.html
next: glossary-zh-CN.html
---
因为React和Web组件是用来解决不同问题的, 试图比较两者将不可避免地导致似是而非的结论, 。Web组件为可复用组件提供了强大的封装, 而React则提供了一个使DOM与你的数据同步的声明式库。两者的目标是互补的工程师可以混合使用这些技术。作为一个开发者你可以在你的Web组件中使用React或者在React中使用Web组件或者两者一起使用。
## 在React中使用Web组件
```javascript
class HelloMessage extends React.Component{
render() {
return <div>Hello <x-search>{this.props.name}</x-search>!</div>;
}
}
```
> 注意:
>
> 两个组件系统的程序模型 (web 组件 与 react 组件) 区别在
> web组件通常暴露一个命令式的API (比如 一个 `video` web 组件可能暴露 `play()`
> 与 `pause()` 函数)。 因为web 组件是它们属性的声明式函数,
> 他们应该可以执行, 但是如果要访问命令式API的一个web组件, 你将需要在组件上附加一个引用
> 并与DOM节点直接交互。如果你在使用第三方web组件,
> 我们推荐你写一个React组件作为你的web组件的封装。
>
> 当前一个由web组件触发的事件可能不能准确地在React渲染树中传递。
> 你将需要手动附加event handlers来在你的react组件中处理这些事件。
## 在Web 组件中使用React
```javascript
var proto = Object.create(HTMLElement.prototype, {
createdCallback: {
value: function() {
var mountPoint = document.createElement('span');
this.createShadowRoot().appendChild(mountPoint);
var name = this.getAttribute('name');
var url = 'https://www.google.com/search?q=' + encodeURIComponent(name);
ReactDOM.render(<a href={url}>{name}</a>, mountPoint);
}
}
});
document.registerElement('x-search', {prototype: proto});
```
## 完整样例
若要查看完整样例,请参照[starter kit](/react/downloads.html)中的`webcomponents`例子。

View File

@@ -137,6 +137,7 @@ This is why you shouldn't construct your own instance. Instead, `ReactElement` i
The `render` method of a `ReactComponent` is expected to return another `ReactElement`. This allows these components to be composed. Ultimately the render resolves into `ReactElement` with a `string` tag which instantiates a DOM `Element` instance and inserts it into the document.
React 0.14 introduced [stateless functional components](/react/blog/2015/10/07/react-v0.14.html#stateless-functional-components) as an alternative way of defining components. Instead of being a class, it is a simple function that accepts props and is expected to return a `ReactElement`.
## Formal Type Definitions
@@ -165,7 +166,7 @@ type ReactDOMElement = {
};
type ReactComponentElement<TProps> = {
type : ReactClass<TProps>,
type : ReactClass<TProps> | ReactFunctionalComponent<TProps>,
props : TProps,
key : string | boolean | number | null,
ref : string | null
@@ -189,5 +190,7 @@ type ReactComponent<TProps> = {
props : TProps,
render : () => ReactElement
};
type ReactFunctionalComponent<TProps> = (TProps) => ReactElement;
```

View File

@@ -134,7 +134,7 @@ You can start seeing how your application will behave: set `filterText` to `"bal
So far, we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in `FilterableProductTable`.
React makes this data flow explicit to make it easy to understand how your program works, but it does require a little more typing than traditional two-way data binding. React provides an add-on called `ReactLink` to make this pattern as convenient as two-way binding, but for the purpose of this post, we'll keep everything explicit.
React makes this data flow explicit to make it easy to understand how your program works, but it does require a little more typing than traditional two-way data binding.
If you try to type or check the box in the current version of the example, you'll see that React ignores your input. This is intentional, as we've set the `value` prop of the `input` to always be equal to the `state` passed in from `FilterableProductTable`.

View File

@@ -27,7 +27,7 @@ It'll also have a few neat features:
In order to start this tutorial, we're going to require a running server. This will serve purely as an API endpoint which we'll use for getting and saving data. In order to make this as easy as possible, we've created a simple server in a number of scripting languages that does exactly what we need it to do. **You can [view the source](https://github.com/reactjs/react-tutorial/) or [download a zip file](https://github.com/reactjs/react-tutorial/archive/master.zip) containing everything needed to get started.**
For sake of simplicity, the server we will run uses a `JSON` file as a database. You would not run this in production but it makes it easy to simulate what you might do when consuming an API. Once you start the server, it will support our API endpoint and it will also serve the static pages we need.
For sake of simplicity, the server we will run uses a `JSON` file as a database. You would not run this in production but it makes it easy to simulate what you might do when consuming an API. Once you [start the server](https://github.com/reactjs/react-tutorial/#to-use), it will support our API endpoint and it will also serve the static pages we need.
### Getting started
@@ -380,8 +380,8 @@ When the component is first created, we want to GET some JSON from the server an
```json
[
{"author": "Pete Hunt", "text": "This is one comment"},
{"author": "Jordan Walke", "text": "This is *another* comment"}
{"id": "1", "author": "Pete Hunt", "text": "This is one comment"},
{"id": "2", "author": "Jordan Walke", "text": "This is *another* comment"}
]
```

View File

@@ -1,6 +1,7 @@
---
id: tutorial-zh-CN
title: 教程
permalink: tutorial-zh-CN.html
prev: getting-started-zh-CN.html
next: thinking-in-react-zh-CN.html
---

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -17,7 +17,7 @@ id: home
<div class="marketing-col">
<h3>Virtual DOM</h3>
<p>
React abstracts away the DOM from you, giving a simpler programming model and better performance. React can also render on the server using Node, and it can power native apps using <a href="https://facebook.github.io/react-native/">React Native</a>.
React abstracts away the DOM, giving a simpler programming model and better performance. React can also render on the server using Node, and it can power native apps using <a href="https://facebook.github.io/react-native/">React Native</a>.
</p>
</div>
<div class="marketing-col">

View File

@@ -1,7 +1,7 @@
/**
* ReactDOM v0.14.7
* ReactDOM v15.0.2
*
* Copyright 2013-2015, Facebook, Inc.
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the

8729
docs/js/react.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -6,11 +6,11 @@
"dependencies": {
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babelify": "^7.2.0",
"browserify": "^11.0.1",
"react": "15.0.0-rc.2",
"react-dom": "15.0.0-rc.2",
"watchify": "^3.4.0"
"babelify": "^7.3.0",
"browserify": "^13.0.0",
"react": "^15.0.2",
"react-dom": "^15.0.2",
"watchify": "^3.7.0"
},
"scripts": {
"build": "browserify ./index.js -t babelify -o bundle.js",

View File

@@ -10,7 +10,7 @@ module.exports = {
archive: './build/react-' + version + '.zip',
},
files: [
{cwd: './build/starter', src: ['**'], dest: 'react-' + version + '/'},
{cwd: './build/starter', src: ['**'], dot: true, dest: 'react-' + version + '/'},
],
},
};

View File

@@ -77,7 +77,7 @@ function writeTempConfig(callback) {
function run(done, configPath) {
grunt.log.writeln('running jest (this may take a while)');
var args = ['--harmony', path.join('node_modules', 'jest-cli', 'bin', 'jest')];
var args = ['--harmony', path.join('node_modules', 'jest-cli', 'bin', 'jest'), '--runInBand'];
if (configPath) {
args.push('--config', configPath);
}

View File

@@ -16,7 +16,7 @@ var addons = {
docs: 'two-way-binding-helpers',
},
Perf: {
module: 'ReactDefaultPerf',
module: 'ReactPerf',
name: 'perf',
docs: 'perf',
},

View File

@@ -0,0 +1,46 @@
'use strict';
var fs = require('fs');
var grunt = require('grunt');
var src = 'packages/react-native-renderer/';
var dest = 'build/packages/react-native-renderer/';
function buildRelease() {
if (grunt.file.exists(dest)) {
grunt.file.delete(dest);
}
// Copy to build/packages/react-native-renderer
var mappings = [].concat(
grunt.file.expandMapping('**/*', dest, {cwd: src}),
grunt.file.expandMapping('{LICENSE,PATENTS}', dest)
);
mappings.forEach(function(mapping) {
var mappingSrc = mapping.src[0];
var mappingDest = mapping.dest;
if (grunt.file.isDir(mappingSrc)) {
grunt.file.mkdir(mappingDest);
} else {
grunt.file.copy(mappingSrc, mappingDest);
}
});
}
function packRelease() {
var done = this.async();
var spawnCmd = {
cmd: 'npm',
args: ['pack', 'packages/react-native-renderer'],
};
grunt.util.spawn(spawnCmd, function() {
var buildSrc = 'react-native-renderer-' + grunt.config.data.pkg.version + '.tgz';
var buildDest = 'build/packages/react-native-renderer.tgz';
fs.rename(buildSrc, buildDest, done);
});
}
module.exports = {
buildRelease: buildRelease,
packRelease: packRelease,
};

View File

@@ -16,7 +16,7 @@ var BOWER_FILES = [
];
var EXAMPLES_PATH = 'examples/';
var EXAMPLES_GLOB = [EXAMPLES_PATH + '**/*.*'];
var EXAMPLES_GLOB = [EXAMPLES_PATH + '**/*.*', EXAMPLES_PATH + '**/.babelrc'];
var STARTER_PATH = 'starter/';
var STARTER_GLOB = [STARTER_PATH + '/**/*.*'];

View File

@@ -11,6 +11,8 @@ module.exports = function() {
grunt.file.readJSON('./packages/react/package.json').version,
'packages/react-dom/package.json':
grunt.file.readJSON('./packages/react-dom/package.json').version,
'packages/react-native-renderer/package.json':
grunt.file.readJSON('./packages/react-native-renderer/package.json').version,
'packages/react-addons/package.json (version)': addonsData.version,
// Get the "version" without the range bit
'packages/react-addons/package.json (react dependency)': addonsData.peerDependencies.react.slice(1),

View File

@@ -20,6 +20,7 @@ var paths = {
react: {
src: [
'src/**/*.js',
'!src/**/__benchmarks__/**/*.js',
'!src/**/__tests__/**/*.js',
'!src/**/__mocks__/**/*.js',
'!src/shared/vendor/**/*.js',
@@ -28,17 +29,31 @@ var paths = {
},
};
var fbjsModuleMap = require('fbjs/module-map');
var moduleMap = {};
for (var key in fbjsModuleMap) {
moduleMap[key] = fbjsModuleMap[key];
}
var whiteListNames = [
'deepDiffer',
'deepFreezeAndThrowOnMutationInDev',
'flattenStyle',
'InitializeJavaScriptAppEngine',
'RCTEventEmitter',
'TextInputState',
'UIManager',
'View',
];
whiteListNames.forEach(function(name) {
moduleMap[name] = name;
});
moduleMap['object-assign'] = 'object-assign';
var babelOpts = {
plugins: [
[babelPluginModules, {
map: Object.assign(
{},
require('fbjs/module-map'),
{
'object-assign': 'object-assign',
}
),
}],
[babelPluginModules, { map: moduleMap }],
],
};

15184
npm-shrinkwrap.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "react-build",
"private": true,
"version": "15.0.0-rc.2",
"version": "15.1.0",
"devDependencies": {
"async": "^1.5.0",
"babel-cli": "^6.6.5",
@@ -25,6 +25,7 @@
"babel-plugin-transform-es2015-template-literals": "^6.5.2",
"babel-plugin-transform-es3-member-expression-literals": "^6.5.0",
"babel-plugin-transform-es3-property-literals": "^6.5.0",
"babel-plugin-transform-object-rest-spread": "^6.6.5",
"babel-preset-react": "^6.5.0",
"browserify": "^13.0.0",
"bundle-collapser": "^1.1.1",
@@ -47,9 +48,9 @@
"gulp-babel": "^6.0.0",
"gulp-flatten": "^0.2.0",
"gzip-js": "~0.3.2",
"jest-cli": "^0.9.0",
"jest-cli": "^12.0.2",
"loose-envify": "^1.1.0",
"object-assign": "^4.0.1",
"object-assign": "^4.1.0",
"platform": "^1.1.0",
"run-sequence": "^1.1.4",
"through2": "^2.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "react-addons-template",
"version": "15.0.0-rc.2",
"version": "15.1.0",
"main": "index.js",
"repository": "facebook/react",
"keywords": [
@@ -10,6 +10,6 @@
"license": "BSD-3-Clause",
"dependencies": {},
"peerDependencies": {
"react": "^15.0.0-rc.2"
"react": "^15.1.0"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "react-dom",
"version": "15.0.0-rc.2",
"version": "15.1.0",
"description": "React package for working with the DOM.",
"main": "index.js",
"repository": "facebook/react",
@@ -14,6 +14,6 @@
"homepage": "https://facebook.github.io/react/",
"dependencies": {},
"peerDependencies": {
"react": "^15.0.0-rc.2"
"react": "^15.1.0"
}
}

View File

@@ -20,6 +20,6 @@
"author": "",
"license": "BSD-3-Clause",
"peerDependencies": {
"react": "^15.0.0-rc.2"
"react": "^15.0.0"
}
}

View File

@@ -0,0 +1,5 @@
# `react-native-renderer`
This package is the renderer that is used by the react-native package.
It is intended to be used inside the react-native environment. It is not
intended to be used stand alone.

View File

@@ -0,0 +1,3 @@
'use strict';
module.exports = require('react/lib/ReactNative');

View File

@@ -0,0 +1,19 @@
{
"name": "react-native-renderer",
"version": "15.1.0",
"description": "React package for use inside react-native.",
"main": "index.js",
"repository": "facebook/react",
"keywords": [
"react",
"react-native"
],
"license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/facebook/react/issues"
},
"homepage": "https://facebook.github.io/react-native/",
"dependencies": {
"react": "^15.1.0"
}
}

View File

@@ -1,12 +0,0 @@
'use strict';
var ReactUpdates = require('./ReactUpdates');
// TODO: In React Native, ReactTestUtils depends on ./ReactDOM (for
// renderIntoDocument, which should never be called) and Relay depends on
// react-dom (for batching). Once those are fixed, nothing in RN should import
// this module and this file can go away.
module.exports = {
unstable_batchedUpdates: ReactUpdates.batchedUpdates,
};

View File

@@ -1,7 +1,7 @@
{
"name": "react",
"description": "React is a JavaScript library for building user interfaces.",
"version": "15.0.0-rc.2",
"version": "15.1.0",
"keywords": [
"react"
],
@@ -25,7 +25,7 @@
"dependencies": {
"fbjs": "^0.8.0",
"loose-envify": "^1.1.0",
"object-assign": "^4.0.1"
"object-assign": "^4.1.0"
},
"browserify": {
"transform": [

View File

@@ -12,6 +12,20 @@
module.exports = function autoImporter(babel) {
const t = babel.types;
function getAssignIdent(path, file, state) {
if (!state.id) {
state.id = path.scope.generateUidIdentifier('assign');
path.scope.getProgramParent().push({
id: state.id,
init: t.callExpression(
t.identifier('require'),
[t.stringLiteral('object-assign')]
),
});
}
return state.id;
}
return {
pre: function() {
// map from module to generated identifier
@@ -22,17 +36,15 @@ module.exports = function autoImporter(babel) {
CallExpression: function(path, file) {
if (path.get('callee').matchesPattern('Object.assign')) {
// generate identifier and require if it hasn't been already
if (!this.id) {
this.id = path.scope.generateUidIdentifier('assign');
path.scope.getProgramParent().push({
id: this.id,
init: t.callExpression(
t.identifier('require'),
[t.stringLiteral('object-assign')]
),
});
}
path.node.callee = this.id;
var id = getAssignIdent(path, file, this);
path.node.callee = id;
}
},
MemberExpression: function(path, file) {
if (path.matchesPattern('Object.assign')) {
var id = getAssignIdent(path, file, this);
path.replaceWith(id);
}
},
},

View File

@@ -11,4 +11,4 @@
'use strict';
module.exports = '15.0.0-rc.2';
module.exports = '15.1.0';

View File

@@ -36,6 +36,8 @@ var shallowCompare = require('shallowCompare');
* complex data structures this mixin may have false-negatives for deeper
* differences. Only mixin to components which have simple props and state, or
* use `forceUpdate()` when you know deep data structures have changed.
*
* See https://facebook.github.io/react/docs/pure-render-mixin.html
*/
var ReactComponentWithPureRenderMixin = {
shouldComponentUpdate: function(nextProps, nextState) {

View File

@@ -31,8 +31,11 @@ var numericPropertyRegex = /^\d+$/;
var warnedAboutNumeric = false;
var ReactFragment = {
// Wrap a keyed object in an opaque proxy that warns you if you access any
// of its properties.
/**
* Wrap a keyed object in an opaque proxy that warns you if you access any
* of its properties.
* See https://facebook.github.io/react/docs/create-fragment.html
*/
create: function(object) {
if (typeof object !== 'object' || !object || Array.isArray(object)) {
warning(

View File

@@ -34,7 +34,7 @@ React.addons = {
};
if (__DEV__) {
React.addons.Perf = require('ReactDefaultPerf');
React.addons.Perf = require('ReactPerf');
React.addons.TestUtils = require('ReactTestUtils');
}

View File

@@ -16,6 +16,7 @@ var ReactStateSetters = require('ReactStateSetters');
/**
* A simple mixin around ReactLink.forState().
* See https://facebook.github.io/react/docs/two-way-binding-helpers.html
*/
var LinkedStateMixin = {
/**

View File

@@ -37,6 +37,9 @@
var React = require('React');
/**
* Deprecated: An an easy way to express two-way binding with React.
* See https://facebook.github.io/react/docs/two-way-binding-helpers.html
*
* @param {*} value current value of the link
* @param {function} requestChange callback to request a change
*/

View File

@@ -16,6 +16,7 @@ var shallowEqual = require('shallowEqual');
/**
* Does a shallow comparison for props and state.
* See ReactComponentWithPureRenderMixin
* See also https://facebook.github.io/react/docs/shallow-compare.html
*/
function shallowCompare(instance, nextProps, nextState) {
return (

View File

@@ -41,6 +41,11 @@ function createTransitionTimeoutPropValidator(transitionType) {
};
}
/**
* An easy way to perform CSS transitions and animations when a React component
* enters or leaves the DOM.
* See https://facebook.github.io/react/docs/animation.html#high-level-api-reactcsstransitiongroup
*/
var ReactCSSTransitionGroup = React.createClass({
displayName: 'ReactCSSTransitionGroup',

View File

@@ -16,6 +16,11 @@ var ReactTransitionChildMapping = require('ReactTransitionChildMapping');
var emptyFunction = require('emptyFunction');
/**
* A basis for animatins. When children are declaratively added or removed,
* special lifecycle hooks are called.
* See https://facebook.github.io/react/docs/animation.html#low-level-api-reacttransitiongroup
*/
var ReactTransitionGroup = React.createClass({
displayName: 'ReactTransitionGroup',

View File

@@ -66,6 +66,10 @@ function invariantArrayCase(value, spec, command) {
);
}
/**
* Returns a updated shallow copy of an object without mutating the original.
* See https://facebook.github.io/react/docs/update.html for details.
*/
function update(value, spec) {
invariant(
typeof spec === 'object',

View File

@@ -13,11 +13,13 @@
var React;
var ReactDOM;
var ReactDOMServer;
describe('ReactErrorBoundaries', function() {
beforeEach(function() {
ReactDOM = require('ReactDOM');
ReactDOMServer = require('ReactDOMServer');
React = require('React');
});
@@ -50,11 +52,46 @@ describe('ReactErrorBoundaries', function() {
var EventPluginHub = require('EventPluginHub');
var container = document.createElement('div');
EventPluginHub.putListener = jest.genMockFn();
EventPluginHub.putListener = jest.fn();
ReactDOM.render(<Boundary />, container);
expect(EventPluginHub.putListener).not.toBeCalled();
});
it('renders an error state (ssr)', function() {
class Angry extends React.Component {
render() {
throw new Error('Please, do not render me.');
}
}
class Boundary extends React.Component {
constructor(props) {
super(props);
this.state = {error: false};
}
render() {
if (!this.state.error) {
return (<div><button onClick={this.onClick}>ClickMe</button><Angry /></div>);
} else {
return (<div>Happy Birthday!</div>);
}
}
onClick() {
/* do nothing */
}
unstable_handleError() {
this.setState({error: true});
}
}
var EventPluginHub = require('EventPluginHub');
var container = document.createElement('div');
EventPluginHub.putListener = jest.fn();
container.innerHTML = ReactDOMServer.renderToString(<Boundary />);
expect(container.firstChild.innerHTML).toBe('Happy Birthday!');
expect(EventPluginHub.putListener).not.toBeCalled();
});
it('will catch exceptions in componentWillUnmount', function() {
class ErrorBoundary extends React.Component {
constructor() {
@@ -120,7 +157,7 @@ describe('ReactErrorBoundaries', function() {
var EventPluginHub = require('EventPluginHub');
var container = document.createElement('div');
EventPluginHub.putListener = jest.genMockFn();
EventPluginHub.putListener = jest.fn();
ReactDOM.render(<Boundary />, container);
expect(EventPluginHub.putListener).toBeCalled();
});

View File

@@ -21,6 +21,7 @@ var ReactPropTypes = require('ReactPropTypes');
var ReactVersion = require('ReactVersion');
var onlyChild = require('onlyChild');
var warning = require('warning');
var createElement = ReactElement.createElement;
var createFactory = ReactElement.createFactory;
@@ -32,6 +33,23 @@ if (__DEV__) {
cloneElement = ReactElementValidator.cloneElement;
}
var __spread = Object.assign;
if (__DEV__) {
var warned = false;
__spread = function() {
warning(
warned,
'React.__spread is deprecated and should not be used. Use ' +
'Object.assign directly or another helper function with similar ' +
'semantics. You may be seeing this warning due to your compiler. ' +
'See https://fb.me/react-spread-deprecation for more details.'
);
warned = true;
return Object.assign.apply(null, arguments);
};
}
var React = {
// Modern
@@ -65,6 +83,9 @@ var React = {
DOM: ReactDOMFactories,
version: ReactVersion,
// Deprecated hook for JSX spread, don't use this for anything.
__spread: __spread,
};
module.exports = React;

View File

@@ -1,124 +0,0 @@
/**
* Copyright 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDebugInstanceMap
*/
'use strict';
var warning = require('warning');
function checkValidInstance(internalInstance) {
if (!internalInstance) {
warning(
false,
'There is an internal error in the React developer tools integration. ' +
'Instead of an internal instance, received %s. ' +
'Please report this as a bug in React.',
internalInstance
);
return false;
}
var isValid = typeof internalInstance.mountComponent === 'function';
warning(
isValid,
'There is an internal error in the React developer tools integration. ' +
'Instead of an internal instance, received an object with the following ' +
'keys: %s. Please report this as a bug in React.',
Object.keys(internalInstance).join(', ')
);
return isValid;
}
var idCounter = 1;
var instancesByIDs = {};
var instancesToIDs;
function getIDForInstance(internalInstance) {
if (!instancesToIDs) {
instancesToIDs = new WeakMap();
}
if (instancesToIDs.has(internalInstance)) {
return instancesToIDs.get(internalInstance);
} else {
var instanceID = (idCounter++).toString();
instancesToIDs.set(internalInstance, instanceID);
return instanceID;
}
}
function getInstanceByID(instanceID) {
return instancesByIDs[instanceID] || null;
}
function isRegisteredInstance(internalInstance) {
var instanceID = getIDForInstance(internalInstance);
if (instanceID) {
return instancesByIDs.hasOwnProperty(instanceID);
} else {
return false;
}
}
function registerInstance(internalInstance) {
var instanceID = getIDForInstance(internalInstance);
if (instanceID) {
instancesByIDs[instanceID] = internalInstance;
}
}
function unregisterInstance(internalInstance) {
var instanceID = getIDForInstance(internalInstance);
if (instanceID) {
delete instancesByIDs[instanceID];
}
}
var ReactDebugInstanceMap = {
getIDForInstance(internalInstance) {
if (!checkValidInstance(internalInstance)) {
return null;
}
return getIDForInstance(internalInstance);
},
getInstanceByID(instanceID) {
return getInstanceByID(instanceID);
},
isRegisteredInstance(internalInstance) {
if (!checkValidInstance(internalInstance)) {
return false;
}
return isRegisteredInstance(internalInstance);
},
registerInstance(internalInstance) {
if (!checkValidInstance(internalInstance)) {
return;
}
warning(
!isRegisteredInstance(internalInstance),
'There is an internal error in the React developer tools integration. ' +
'A registered instance should not be registered again. ' +
'Please report this as a bug in React.'
);
registerInstance(internalInstance);
},
unregisterInstance(internalInstance) {
if (!checkValidInstance(internalInstance)) {
return;
}
warning(
isRegisteredInstance(internalInstance),
'There is an internal error in the React developer tools integration. ' +
'An unregistered instance should not be unregistered again. ' +
'Please report this as a bug in React.'
);
unregisterInstance(internalInstance);
},
};
module.exports = ReactDebugInstanceMap;

View File

@@ -11,7 +11,9 @@
'use strict';
var ReactInvalidSetStateWarningDevTool = require('ReactInvalidSetStateWarningDevTool');
var ExecutionEnvironment = require('ExecutionEnvironment');
var performanceNow = require('performanceNow');
var warning = require('warning');
var eventHandlers = [];
@@ -37,6 +39,70 @@ function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {
}
}
var isProfiling = false;
var flushHistory = [];
var currentFlushNesting = 0;
var currentFlushMeasurements = null;
var currentFlushStartTime = null;
var currentTimerDebugID = null;
var currentTimerStartTime = null;
var currentTimerType = null;
function clearHistory() {
ReactComponentTreeDevtool.purgeUnmountedComponents();
ReactNativeOperationHistoryDevtool.clearHistory();
}
function getTreeSnapshot(registeredIDs) {
return registeredIDs.reduce((tree, id) => {
var ownerID = ReactComponentTreeDevtool.getOwnerID(id);
var parentID = ReactComponentTreeDevtool.getParentID(id);
tree[id] = {
displayName: ReactComponentTreeDevtool.getDisplayName(id),
text: ReactComponentTreeDevtool.getText(id),
updateCount: ReactComponentTreeDevtool.getUpdateCount(id),
childIDs: ReactComponentTreeDevtool.getChildIDs(id),
// Text nodes don't have owners but this is close enough.
ownerID: ownerID || ReactComponentTreeDevtool.getOwnerID(parentID),
parentID,
};
return tree;
}, {});
}
function resetMeasurements() {
if (__DEV__) {
var previousStartTime = currentFlushStartTime;
var previousMeasurements = currentFlushMeasurements || [];
var previousOperations = ReactNativeOperationHistoryDevtool.getHistory();
if (!isProfiling || currentFlushNesting === 0) {
currentFlushStartTime = null;
currentFlushMeasurements = null;
clearHistory();
return;
}
if (previousMeasurements.length || previousOperations.length) {
var registeredIDs = ReactComponentTreeDevtool.getRegisteredIDs();
flushHistory.push({
duration: performanceNow() - previousStartTime,
measurements: previousMeasurements || [],
operations: previousOperations || [],
treeSnapshot: getTreeSnapshot(registeredIDs),
});
}
clearHistory();
currentFlushStartTime = performanceNow();
currentFlushMeasurements = [];
}
}
function checkDebugID(debugID) {
warning(debugID, 'ReactDebugTool: debugID may not be empty.');
}
var ReactDebugTool = {
addDevtool(devtool) {
eventHandlers.push(devtool);
@@ -49,29 +115,157 @@ var ReactDebugTool = {
}
}
},
beginProfiling() {
if (__DEV__) {
if (isProfiling) {
return;
}
isProfiling = true;
flushHistory.length = 0;
resetMeasurements();
}
},
endProfiling() {
if (__DEV__) {
if (!isProfiling) {
return;
}
isProfiling = false;
resetMeasurements();
}
},
getFlushHistory() {
if (__DEV__) {
return flushHistory;
}
},
onBeginFlush() {
if (__DEV__) {
currentFlushNesting++;
resetMeasurements();
}
emitEvent('onBeginFlush');
},
onEndFlush() {
if (__DEV__) {
resetMeasurements();
currentFlushNesting--;
}
emitEvent('onEndFlush');
},
onBeginLifeCycleTimer(debugID, timerType) {
checkDebugID(debugID);
emitEvent('onBeginLifeCycleTimer', debugID, timerType);
if (__DEV__) {
if (isProfiling && currentFlushNesting > 0) {
warning(
!currentTimerType,
'There is an internal error in the React performance measurement code. ' +
'Did not expect %s timer to start while %s timer is still in ' +
'progress for %s instance.',
timerType,
currentTimerType || 'no',
(debugID === currentTimerDebugID) ? 'the same' : 'another'
);
currentTimerStartTime = performanceNow();
currentTimerDebugID = debugID;
currentTimerType = timerType;
}
}
},
onEndLifeCycleTimer(debugID, timerType) {
checkDebugID(debugID);
if (__DEV__) {
if (isProfiling && currentFlushNesting > 0) {
warning(
currentTimerType === timerType,
'There is an internal error in the React performance measurement code. ' +
'We did not expect %s timer to stop while %s timer is still in ' +
'progress for %s instance. Please report this as a bug in React.',
timerType,
currentTimerType || 'no',
(debugID === currentTimerDebugID) ? 'the same' : 'another'
);
currentFlushMeasurements.push({
timerType,
instanceID: debugID,
duration: performanceNow() - currentTimerStartTime,
});
currentTimerStartTime = null;
currentTimerDebugID = null;
currentTimerType = null;
}
}
emitEvent('onEndLifeCycleTimer', debugID, timerType);
},
onBeginReconcilerTimer(debugID, timerType) {
checkDebugID(debugID);
emitEvent('onBeginReconcilerTimer', debugID, timerType);
},
onEndReconcilerTimer(debugID, timerType) {
checkDebugID(debugID);
emitEvent('onEndReconcilerTimer', debugID, timerType);
},
onBeginProcessingChildContext() {
emitEvent('onBeginProcessingChildContext');
},
onEndProcessingChildContext() {
emitEvent('onEndProcessingChildContext');
},
onNativeOperation(debugID, type, payload) {
checkDebugID(debugID);
emitEvent('onNativeOperation', debugID, type, payload);
},
onSetState() {
emitEvent('onSetState');
},
onMountRootComponent(internalInstance) {
emitEvent('onMountRootComponent', internalInstance);
onSetDisplayName(debugID, displayName) {
checkDebugID(debugID);
emitEvent('onSetDisplayName', debugID, displayName);
},
onMountComponent(internalInstance) {
emitEvent('onMountComponent', internalInstance);
onSetChildren(debugID, childDebugIDs) {
checkDebugID(debugID);
emitEvent('onSetChildren', debugID, childDebugIDs);
},
onUpdateComponent(internalInstance) {
emitEvent('onUpdateComponent', internalInstance);
onSetOwner(debugID, ownerDebugID) {
checkDebugID(debugID);
emitEvent('onSetOwner', debugID, ownerDebugID);
},
onUnmountComponent(internalInstance) {
emitEvent('onUnmountComponent', internalInstance);
onSetText(debugID, text) {
checkDebugID(debugID);
emitEvent('onSetText', debugID, text);
},
onMountRootComponent(debugID) {
checkDebugID(debugID);
emitEvent('onMountRootComponent', debugID);
},
onMountComponent(debugID) {
checkDebugID(debugID);
emitEvent('onMountComponent', debugID);
},
onUpdateComponent(debugID) {
checkDebugID(debugID);
emitEvent('onUpdateComponent', debugID);
},
onUnmountComponent(debugID) {
checkDebugID(debugID);
emitEvent('onUnmountComponent', debugID);
},
};
ReactDebugTool.addDevtool(ReactInvalidSetStateWarningDevTool);
if (__DEV__) {
var ReactInvalidSetStateWarningDevTool = require('ReactInvalidSetStateWarningDevTool');
var ReactNativeOperationHistoryDevtool = require('ReactNativeOperationHistoryDevtool');
var ReactComponentTreeDevtool = require('ReactComponentTreeDevtool');
ReactDebugTool.addDevtool(ReactInvalidSetStateWarningDevTool);
ReactDebugTool.addDevtool(ReactComponentTreeDevtool);
ReactDebugTool.addDevtool(ReactNativeOperationHistoryDevtool);
var url = (ExecutionEnvironment.canUseDOM && window.location.href) || '';
if ((/[?&]react_perf\b/).test(url)) {
ReactDebugTool.beginProfiling();
}
}
module.exports = ReactDebugTool;

371
src/isomorphic/ReactPerf.js Normal file
View File

@@ -0,0 +1,371 @@
/**
* Copyright 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactPerf
*/
'use strict';
var ReactDebugTool = require('ReactDebugTool');
var warning = require('warning');
function roundFloat(val, base = 2) {
var n = Math.pow(10, base);
return Math.floor(val * n) / n;
}
function getFlushHistory() {
return ReactDebugTool.getFlushHistory();
}
function getExclusive(flushHistory = getFlushHistory()) {
var aggregatedStats = {};
var affectedIDs = {};
function updateAggregatedStats(treeSnapshot, instanceID, timerType, applyUpdate) {
var {displayName} = treeSnapshot[instanceID];
var key = displayName;
var stats = aggregatedStats[key];
if (!stats) {
affectedIDs[key] = {};
stats = aggregatedStats[key] = {
key,
instanceCount: 0,
counts: {},
durations: {},
totalDuration: 0,
};
}
if (!stats.durations[timerType]) {
stats.durations[timerType] = 0;
}
if (!stats.counts[timerType]) {
stats.counts[timerType] = 0;
}
affectedIDs[key][instanceID] = true;
applyUpdate(stats);
}
flushHistory.forEach(flush => {
var {measurements, treeSnapshot} = flush;
measurements.forEach(measurement => {
var {duration, instanceID, timerType} = measurement;
updateAggregatedStats(treeSnapshot, instanceID, timerType, stats => {
stats.totalDuration += duration;
stats.durations[timerType] += duration;
stats.counts[timerType]++;
});
});
});
return Object.keys(aggregatedStats)
.map(key => ({
...aggregatedStats[key],
instanceCount: Object.keys(affectedIDs[key]).length,
}))
.sort((a, b) =>
b.totalDuration - a.totalDuration
);
}
function getInclusive(flushHistory = getFlushHistory()) {
var aggregatedStats = {};
var affectedIDs = {};
function updateAggregatedStats(treeSnapshot, instanceID, applyUpdate) {
var {displayName, ownerID} = treeSnapshot[instanceID];
var owner = treeSnapshot[ownerID];
var key = (owner ? owner.displayName + ' > ' : '') + displayName;
var stats = aggregatedStats[key];
if (!stats) {
affectedIDs[key] = {};
stats = aggregatedStats[key] = {
key,
instanceCount: 0,
inclusiveRenderDuration: 0,
renderCount: 0,
};
}
affectedIDs[key][instanceID] = true;
applyUpdate(stats);
}
var isCompositeByID = {};
flushHistory.forEach(flush => {
var {measurements} = flush;
measurements.forEach(measurement => {
var {instanceID, timerType} = measurement;
if (timerType !== 'render') {
return;
}
isCompositeByID[instanceID] = true;
});
});
flushHistory.forEach(flush => {
var {measurements, treeSnapshot} = flush;
measurements.forEach(measurement => {
var {duration, instanceID, timerType} = measurement;
if (timerType !== 'render') {
return;
}
updateAggregatedStats(treeSnapshot, instanceID, stats => {
stats.renderCount++;
});
var nextParentID = instanceID;
while (nextParentID) {
// As we traverse parents, only count inclusive time towards composites.
// We know something is a composite if its render() was called.
if (isCompositeByID[nextParentID]) {
updateAggregatedStats(treeSnapshot, nextParentID, stats => {
stats.inclusiveRenderDuration += duration;
});
}
nextParentID = treeSnapshot[nextParentID].parentID;
}
});
});
return Object.keys(aggregatedStats)
.map(key => ({
...aggregatedStats[key],
instanceCount: Object.keys(affectedIDs[key]).length,
}))
.sort((a, b) =>
b.inclusiveRenderDuration - a.inclusiveRenderDuration
);
}
function getWasted(flushHistory = getFlushHistory()) {
var aggregatedStats = {};
var affectedIDs = {};
function updateAggregatedStats(treeSnapshot, instanceID, applyUpdate) {
var {displayName, ownerID} = treeSnapshot[instanceID];
var owner = treeSnapshot[ownerID];
var key = (owner ? owner.displayName + ' > ' : '') + displayName;
var stats = aggregatedStats[key];
if (!stats) {
affectedIDs[key] = {};
stats = aggregatedStats[key] = {
key,
instanceCount: 0,
inclusiveRenderDuration: 0,
renderCount: 0,
};
}
affectedIDs[key][instanceID] = true;
applyUpdate(stats);
}
flushHistory.forEach(flush => {
var {measurements, treeSnapshot, operations} = flush;
var isDefinitelyNotWastedByID = {};
// Find native components associated with an operation in this batch.
// Mark all components in their parent tree as definitely not wasted.
operations.forEach(operation => {
var {instanceID} = operation;
var nextParentID = instanceID;
while (nextParentID) {
isDefinitelyNotWastedByID[nextParentID] = true;
nextParentID = treeSnapshot[nextParentID].parentID;
}
});
// Find composite components that rendered in this batch.
// These are potential candidates for being wasted renders.
var renderedCompositeIDs = {};
measurements.forEach(measurement => {
var {instanceID, timerType} = measurement;
if (timerType !== 'render') {
return;
}
renderedCompositeIDs[instanceID] = true;
});
measurements.forEach(measurement => {
var {duration, instanceID, timerType} = measurement;
if (timerType !== 'render') {
return;
}
// If there was a DOM update below this component, or it has just been
// mounted, its render() is not considered wasted.
var { updateCount } = treeSnapshot[instanceID];
if (isDefinitelyNotWastedByID[instanceID] || updateCount === 0) {
return;
}
// We consider this render() wasted.
updateAggregatedStats(treeSnapshot, instanceID, stats => {
stats.renderCount++;
});
var nextParentID = instanceID;
while (nextParentID) {
// Any parents rendered during this batch are considered wasted
// unless we previously marked them as dirty.
var isWasted =
renderedCompositeIDs[nextParentID] &&
!isDefinitelyNotWastedByID[nextParentID];
if (isWasted) {
updateAggregatedStats(treeSnapshot, nextParentID, stats => {
stats.inclusiveRenderDuration += duration;
});
}
nextParentID = treeSnapshot[nextParentID].parentID;
}
});
});
return Object.keys(aggregatedStats)
.map(key => ({
...aggregatedStats[key],
instanceCount: Object.keys(affectedIDs[key]).length,
}))
.sort((a, b) =>
b.inclusiveRenderDuration - a.inclusiveRenderDuration
);
}
function getOperations(flushHistory = getFlushHistory()) {
var stats = [];
flushHistory.forEach((flush, flushIndex) => {
var {operations, treeSnapshot} = flush;
operations.forEach(operation => {
var {instanceID, type, payload} = operation;
var {displayName, ownerID} = treeSnapshot[instanceID];
var owner = treeSnapshot[ownerID];
var key = (owner ? owner.displayName + ' > ' : '') + displayName;
stats.push({
flushIndex,
instanceID,
key,
type,
ownerID,
payload,
});
});
});
return stats;
}
function printExclusive(flushHistory) {
var stats = getExclusive(flushHistory);
var table = stats.map(item => {
var {key, instanceCount, totalDuration} = item;
var renderCount = item.counts.render || 0;
var renderDuration = item.durations.render || 0;
return {
'Component': key,
'Total time (ms)': roundFloat(totalDuration),
'Instance count': instanceCount,
'Total render time (ms)': roundFloat(renderDuration),
'Average render time (ms)': renderCount ?
roundFloat(renderDuration / renderCount) :
undefined,
'Render count': renderCount,
'Total lifecycle time (ms)': roundFloat(totalDuration - renderDuration),
};
});
console.table(table);
}
function printInclusive(flushHistory) {
var stats = getInclusive(flushHistory);
var table = stats.map(item => {
var {key, instanceCount, inclusiveRenderDuration, renderCount} = item;
return {
'Owner > Component': key,
'Inclusive render time (ms)': roundFloat(inclusiveRenderDuration),
'Instance count': instanceCount,
'Render count': renderCount,
};
});
console.table(table);
}
function printWasted(flushHistory) {
var stats = getWasted(flushHistory);
var table = stats.map(item => {
var {key, instanceCount, inclusiveRenderDuration, renderCount} = item;
return {
'Owner > Component': key,
'Inclusive wasted time (ms)': roundFloat(inclusiveRenderDuration),
'Instance count': instanceCount,
'Render count': renderCount,
};
});
console.table(table);
}
function printOperations(flushHistory) {
var stats = getOperations(flushHistory);
var table = stats.map(stat => ({
'Owner > Node': stat.key,
'Operation': stat.type,
'Payload': typeof stat.payload === 'object' ?
JSON.stringify(stat.payload) :
stat.payload,
'Flush index': stat.flushIndex,
'Owner Component ID': stat.ownerID,
'DOM Component ID': stat.instanceID,
}));
console.table(table);
}
var warnedAboutPrintDOM = false;
function printDOM(measurements) {
warning(
warnedAboutPrintDOM,
'`ReactPerf.printDOM(...)` is deprecated. Use ' +
'`ReactPerf.printOperations(...)` instead.'
);
warnedAboutPrintDOM = true;
return printOperations(measurements);
}
var warnedAboutGetMeasurementsSummaryMap = false;
function getMeasurementsSummaryMap(measurements) {
warning(
warnedAboutGetMeasurementsSummaryMap,
'`ReactPerf.getMeasurementsSummaryMap(...)` is deprecated. Use ' +
'`ReactPerf.getWasted(...)` instead.'
);
warnedAboutGetMeasurementsSummaryMap = true;
return getWasted(measurements);
}
function start() {
ReactDebugTool.beginProfiling();
}
function stop() {
ReactDebugTool.endProfiling();
}
var ReactPerfAnalysis = {
getLastMeasurements: getFlushHistory,
getExclusive,
getInclusive,
getWasted,
getOperations,
printExclusive,
printInclusive,
printWasted,
printOperations,
start,
stop,
// Deprecated:
printDOM,
getMeasurementsSummaryMap,
};
module.exports = ReactPerfAnalysis;

View File

@@ -1,173 +0,0 @@
/**
* Copyright 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @emails react-core
*/
'use strict';
describe('ReactDebugInstanceMap', function() {
var React;
var ReactDebugInstanceMap;
var ReactDOM;
beforeEach(function() {
jest.resetModuleRegistry();
React = require('React');
ReactDebugInstanceMap = require('ReactDebugInstanceMap');
ReactDOM = require('ReactDOM');
});
function createStubInstance() {
return { mountComponent: () => {} };
}
it('should register and unregister instances', function() {
var inst1 = createStubInstance();
var inst2 = createStubInstance();
expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(false);
expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(false);
ReactDebugInstanceMap.registerInstance(inst1);
expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(true);
expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(false);
ReactDebugInstanceMap.registerInstance(inst2);
expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(true);
expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(true);
ReactDebugInstanceMap.unregisterInstance(inst2);
expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(true);
expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(false);
ReactDebugInstanceMap.unregisterInstance(inst1);
expect(ReactDebugInstanceMap.isRegisteredInstance(inst1)).toBe(false);
expect(ReactDebugInstanceMap.isRegisteredInstance(inst2)).toBe(false);
});
it('should assign stable IDs', function() {
var inst1 = createStubInstance();
var inst2 = createStubInstance();
var inst1ID = ReactDebugInstanceMap.getIDForInstance(inst1);
var inst2ID = ReactDebugInstanceMap.getIDForInstance(inst2);
expect(typeof inst1ID).toBe('string');
expect(typeof inst2ID).toBe('string');
expect(inst1ID).not.toBe(inst2ID);
ReactDebugInstanceMap.registerInstance(inst1);
ReactDebugInstanceMap.registerInstance(inst2);
expect(ReactDebugInstanceMap.getIDForInstance(inst1)).toBe(inst1ID);
expect(ReactDebugInstanceMap.getIDForInstance(inst2)).toBe(inst2ID);
ReactDebugInstanceMap.unregisterInstance(inst1);
ReactDebugInstanceMap.unregisterInstance(inst2);
expect(ReactDebugInstanceMap.getIDForInstance(inst1)).toBe(inst1ID);
expect(ReactDebugInstanceMap.getIDForInstance(inst2)).toBe(inst2ID);
});
it('should retrieve registered instance by its ID', function() {
var inst1 = createStubInstance();
var inst2 = createStubInstance();
var inst1ID = ReactDebugInstanceMap.getIDForInstance(inst1);
var inst2ID = ReactDebugInstanceMap.getIDForInstance(inst2);
expect(ReactDebugInstanceMap.getInstanceByID(inst1ID)).toBe(null);
expect(ReactDebugInstanceMap.getInstanceByID(inst2ID)).toBe(null);
ReactDebugInstanceMap.registerInstance(inst1);
ReactDebugInstanceMap.registerInstance(inst2);
expect(ReactDebugInstanceMap.getInstanceByID(inst1ID)).toBe(inst1);
expect(ReactDebugInstanceMap.getInstanceByID(inst2ID)).toBe(inst2);
ReactDebugInstanceMap.unregisterInstance(inst1);
ReactDebugInstanceMap.unregisterInstance(inst2);
expect(ReactDebugInstanceMap.getInstanceByID(inst1ID)).toBe(null);
expect(ReactDebugInstanceMap.getInstanceByID(inst2ID)).toBe(null);
});
it('should warn when registering an instance twice', function() {
spyOn(console, 'error');
var inst = createStubInstance();
ReactDebugInstanceMap.registerInstance(inst);
expect(console.error.argsForCall.length).toBe(0);
ReactDebugInstanceMap.registerInstance(inst);
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain(
'There is an internal error in the React developer tools integration. ' +
'A registered instance should not be registered again. ' +
'Please report this as a bug in React.'
);
ReactDebugInstanceMap.unregisterInstance(inst);
ReactDebugInstanceMap.registerInstance(inst);
expect(console.error.argsForCall.length).toBe(1);
});
it('should warn when unregistering an instance twice', function() {
spyOn(console, 'error');
var inst = createStubInstance();
ReactDebugInstanceMap.unregisterInstance(inst);
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain(
'There is an internal error in the React developer tools integration. ' +
'An unregistered instance should not be unregistered again. ' +
'Please report this as a bug in React.'
);
ReactDebugInstanceMap.registerInstance(inst);
ReactDebugInstanceMap.unregisterInstance(inst);
expect(console.error.argsForCall.length).toBe(1);
ReactDebugInstanceMap.unregisterInstance(inst);
expect(console.error.argsForCall.length).toBe(2);
expect(console.error.argsForCall[1][0]).toContain(
'There is an internal error in the React developer tools integration. ' +
'An unregistered instance should not be unregistered again. ' +
'Please report this as a bug in React.'
);
});
it('should warn about anything than is not an internal instance', function() {
class Foo extends React.Component {
render() {
return <div />;
}
}
spyOn(console, 'error');
var warningCount = 0;
var div = document.createElement('div');
var publicInst = ReactDOM.render(<Foo />, div);
[false, null, undefined, {}, div, publicInst].forEach(falsyValue => {
ReactDebugInstanceMap.registerInstance(falsyValue);
warningCount++;
expect(ReactDebugInstanceMap.getIDForInstance(falsyValue)).toBe(null);
warningCount++;
expect(ReactDebugInstanceMap.isRegisteredInstance(falsyValue)).toBe(false);
warningCount++;
ReactDebugInstanceMap.unregisterInstance(falsyValue);
warningCount++;
});
expect(console.error.argsForCall.length).toBe(warningCount);
for (var i = 0; i < warningCount.length; i++) {
// Ideally we could check for the more detailed error message here
// but it depends on the input type and is meant for internal bugs
// anyway so I don't think it's worth complicating the test with it.
expect(console.error.argsForCall[i][0]).toContain(
'There is an internal error in the React developer tools integration.'
);
}
});
});

View File

@@ -11,13 +11,11 @@
'use strict';
describe('ReactDefaultPerf', function() {
describe('ReactPerf', function() {
var React;
var ReactDOM;
var ReactDOMFeatureFlags;
var ReactDefaultPerf;
var ReactPerf;
var ReactTestUtils;
var ReactDefaultPerfAnalysis;
var App;
var Box;
@@ -36,10 +34,8 @@ describe('ReactDefaultPerf', function() {
React = require('React');
ReactDOM = require('ReactDOM');
ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
ReactDefaultPerf = require('ReactDefaultPerf');
ReactPerf = require('ReactPerf');
ReactTestUtils = require('ReactTestUtils');
ReactDefaultPerfAnalysis = require('ReactDefaultPerfAnalysis');
App = React.createClass({
render: function() {
@@ -68,10 +64,17 @@ describe('ReactDefaultPerf', function() {
});
function measure(fn) {
ReactDefaultPerf.start();
ReactPerf.start();
fn();
ReactDefaultPerf.stop();
return ReactDefaultPerf.getLastMeasurements().__unstable_this_format_will_change;
ReactPerf.stop();
// Make sure none of the methods crash.
ReactPerf.getWasted();
ReactPerf.getInclusive();
ReactPerf.getExclusive();
ReactPerf.getOperations();
return ReactPerf.getLastMeasurements();
}
it('should count no-op update as waste', function() {
@@ -81,20 +84,18 @@ describe('ReactDefaultPerf', function() {
ReactDOM.render(<App />, container);
});
var summary = ReactDefaultPerf.getWasted(measurements);
expect(summary.length).toBe(2);
/*eslint-disable dot-notation */
expect(summary[0]['Owner > component']).toBe('<root> > App');
expect(summary[0]['Wasted time (ms)']).not.toBe(0);
expect(summary[0]['Instances']).toBe(1);
expect(summary[1]['Owner > component']).toBe('App > Box');
expect(summary[1]['Wasted time (ms)']).not.toBe(0);
expect(summary[1]['Instances']).toBe(2);
/*eslint-enable dot-notation */
var summary = ReactPerf.getWasted(measurements);
expect(summary).toEqual([{
key: 'App',
instanceCount: 1,
inclusiveRenderDuration: 3,
renderCount: 1,
}, {
key: 'App > Box',
instanceCount: 2,
inclusiveRenderDuration: 2,
renderCount: 2,
}]);
});
it('should count no-op update in child as waste', function() {
@@ -107,21 +108,18 @@ describe('ReactDefaultPerf', function() {
ReactDOM.render(<App flipSecond={true} />, container);
});
var summary = ReactDefaultPerf.getWasted(measurements);
expect(summary.length).toBe(1);
/*eslint-disable dot-notation */
expect(summary[0]['Owner > component']).toBe('App > Box');
expect(summary[0]['Wasted time (ms)']).not.toBe(0);
expect(summary[0]['Instances']).toBe(1);
/*eslint-enable dot-notation */
var summary = ReactPerf.getWasted(measurements);
expect(summary).toEqual([{
key: 'App > Box',
instanceCount: 1,
inclusiveRenderDuration: 1,
renderCount: 1,
}]);
});
function expectNoWaste(fn) {
var measurements = measure(fn);
var summary = ReactDefaultPerf.getWasted(measurements);
var summary = ReactPerf.getWasted(measurements);
expect(summary).toEqual([]);
}
@@ -217,71 +215,72 @@ describe('ReactDefaultPerf', function() {
});
});
it('putListener should not be instrumented', function() {
it('should not count replacing null with a native as waste', function() {
var element = null;
function Foo() {
return element;
}
var container = document.createElement('div');
ReactDOM.render(<Div onClick={function() {}}>hey</Div>, container);
var measurements = measure(() => {
ReactDOM.render(<Div onClick={function() {}}>hey</Div>, container);
ReactDOM.render(<Foo />, container);
expectNoWaste(() => {
element = <div />;
ReactDOM.render(<Foo />, container);
});
var summary = ReactDefaultPerfAnalysis.getDOMSummary(measurements);
expect(summary).toEqual([]);
});
it('deleteListener should not be instrumented', function() {
it('should not count replacing a native with null as waste', function() {
var element = <div />;
function Foo() {
return element;
}
var container = document.createElement('div');
ReactDOM.render(<Div onClick={function() {}}>hey</Div>, container);
var measurements = measure(() => {
ReactDOM.render(<Div>hey</Div>, container);
ReactDOM.render(<Foo />, container);
expectNoWaste(() => {
element = null;
ReactDOM.render(<Foo />, container);
});
var summary = ReactDefaultPerfAnalysis.getDOMSummary(measurements);
expect(summary).toEqual([]);
});
it('should print a table after calling printOperations', function() {
it('should include stats for components unmounted during measurement', function() {
var container = document.createElement('div');
var measurements = measure(() => {
ReactDOM.render(<Div>hey</Div>, container);
ReactDOM.render(<Div><Div key="a" /></Div>, container);
ReactDOM.render(<Div><Div key="b" /></Div>, container);
});
spyOn(console, 'table');
ReactDefaultPerf.printOperations(measurements);
expect(console.table.calls.length).toBe(1);
expect(console.table.argsForCall[0][0]).toEqual([{
'data-reactid': '',
type: 'set innerHTML',
args: ReactDOMFeatureFlags.useCreateElement ?
'{"node":"<not serializable>","children":[],"html":null,"text":null}' :
'"<div data-reactroot=\\"\\" data-reactid=\\"1\\">hey</div>"',
expect(ReactPerf.getExclusive(measurements)).toEqual([{
key: 'Div',
instanceCount: 3,
counts: { ctor: 3, render: 4 },
durations: { ctor: 3, render: 4 },
totalDuration: 7,
}]);
});
it('warns once when using getMeasurementsSummaryMap', function() {
var measurements = measure(() => {});
spyOn(console, 'error');
ReactDefaultPerf.getMeasurementsSummaryMap(measurements);
ReactPerf.getMeasurementsSummaryMap(measurements);
expect(console.error.calls.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain(
'`ReactPerf.getMeasurementsSummaryMap(...)` is deprecated. Use ' +
'`ReactPerf.getWasted(...)` instead.'
);
ReactDefaultPerf.getMeasurementsSummaryMap(measurements);
ReactPerf.getMeasurementsSummaryMap(measurements);
expect(console.error.calls.length).toBe(1);
});
it('warns once when using printDOM', function() {
var measurements = measure(() => {});
spyOn(console, 'error');
ReactDefaultPerf.printDOM(measurements);
ReactPerf.printDOM(measurements);
expect(console.error.calls.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain(
'`ReactPerf.printDOM(...)` is deprecated. Use ' +
'`ReactPerf.printOperations(...)` instead.'
);
ReactDefaultPerf.printDOM(measurements);
ReactPerf.printDOM(measurements);
expect(console.error.calls.length).toBe(1);
});
});

View File

@@ -55,6 +55,8 @@ function forEachSingleChild(bookKeeping, child, name) {
/**
* Iterates through children that are typically specified as `props.children`.
*
* See https://facebook.github.io/react/docs/top-level-api.html#react.children.foreach
*
* The provided forEachFunc(child, index) will be called for each
* leaf child.
*
@@ -146,6 +148,8 @@ function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
/**
* Maps children that are typically specified as `props.children`.
*
* See https://facebook.github.io/react/docs/top-level-api.html#react.children.map
*
* The provided mapFunction(child, key, index) will be called for each
* leaf child.
*
@@ -173,6 +177,8 @@ function forEachSingleChildDummy(traverseContext, child, name) {
* Count the number of children that are typically specified as
* `props.children`.
*
* See https://facebook.github.io/react/docs/top-level-api.html#react.children.count
*
* @param {?*} children Children tree container.
* @return {number} The number of children.
*/
@@ -184,6 +190,8 @@ function countChildren(children, context) {
/**
* Flatten a children object (typically specified as `props.children`) and
* return an array with appropriately re-keyed children.
*
* See https://facebook.github.io/react/docs/top-level-api.html#react.children.toarray
*/
function toArray(children) {
var result = [];

View File

@@ -16,13 +16,16 @@ var invariant = require('invariant');
/**
* Returns the first child in a collection of children and verifies that there
* is only one child in the collection. The current implementation of this
* function assumes that a single child gets passed without a wrapper, but the
* purpose of this helper function is to abstract away the particular structure
* of children.
* is only one child in the collection.
*
* See https://facebook.github.io/react/docs/top-level-api.html#react.children.only
*
* The current implementation of this function assumes that a single child gets
* passed without a wrapper, but the purpose of this helper function is to
* abstract away the particular structure of children.
*
* @param {?object} children Child collection structure.
* @return {ReactComponent} The first and only `ReactComponent` contained in the
* @return {ReactElement} The first and only `ReactElement` contained in the
* structure.
*/
function onlyChild(children) {

View File

@@ -740,6 +740,7 @@ var ReactClass = {
/**
* Creates a composite component class given a class specification.
* See https://facebook.github.io/react/docs/top-level-api.html#react.createclass
*
* @param {object} spec Class specification (which must define `render`).
* @return {function} Component constructor function.

View File

@@ -20,9 +20,9 @@ describe('autobinding', function() {
it('Holds reference to instance', function() {
var mouseDidEnter = jest.genMockFn();
var mouseDidLeave = jest.genMockFn();
var mouseDidClick = jest.genMockFn();
var mouseDidEnter = jest.fn();
var mouseDidLeave = jest.fn();
var mouseDidClick = jest.fn();
var TestBindComponent = React.createClass({
getInitialState: function() {
@@ -95,7 +95,7 @@ describe('autobinding', function() {
});
it('works with mixins', function() {
var mouseDidClick = jest.genMockFn();
var mouseDidClick = jest.fn();
var TestMixin = {
onClick: mouseDidClick,

View File

@@ -20,9 +20,9 @@ describe('autobind optout', function() {
it('should work with manual binding', function() {
var mouseDidEnter = jest.genMockFn();
var mouseDidLeave = jest.genMockFn();
var mouseDidClick = jest.genMockFn();
var mouseDidEnter = jest.fn();
var mouseDidLeave = jest.fn();
var mouseDidClick = jest.fn();
var TestBindComponent = React.createClass({
autobind: false,
@@ -138,7 +138,7 @@ describe('autobind optout', function() {
});
it('works with mixins that have not opted out of autobinding', function() {
var mouseDidClick = jest.genMockFn();
var mouseDidClick = jest.fn();
var TestMixin = {
onClick: mouseDidClick,
@@ -164,7 +164,7 @@ describe('autobind optout', function() {
});
it('works with mixins that have opted out of autobinding', function() {
var mouseDidClick = jest.genMockFn();
var mouseDidClick = jest.fn();
var TestMixin = {
autobind: false,

View File

@@ -43,7 +43,7 @@ describe('ReactClass-spec', function() {
});
it('should copy prop types onto the Constructor', function() {
var propValidator = jest.genMockFn();
var propValidator = jest.fn();
var TestComponent = React.createClass({
propTypes: {
value: propValidator,

View File

@@ -25,8 +25,8 @@ describe('ReactClass-mixin', function() {
beforeEach(function() {
React = require('React');
ReactTestUtils = require('ReactTestUtils');
mixinPropValidator = jest.genMockFn();
componentPropValidator = jest.genMockFn();
mixinPropValidator = jest.fn();
componentPropValidator = jest.fn();
var MixinA = {
propTypes: {
@@ -107,7 +107,7 @@ describe('ReactClass-mixin', function() {
});
it('should support merging propTypes and statics', function() {
var listener = jest.genMockFn();
var listener = jest.fn();
var instance = <TestComponent listener={listener} />;
instance = ReactTestUtils.renderIntoDocument(instance);
@@ -122,7 +122,7 @@ describe('ReactClass-mixin', function() {
});
it('should support chaining delegate functions', function() {
var listener = jest.genMockFn();
var listener = jest.fn();
var instance = <TestComponent listener={listener} />;
instance = ReactTestUtils.renderIntoDocument(instance);
@@ -135,7 +135,7 @@ describe('ReactClass-mixin', function() {
});
it('should chain functions regardless of spec property order', function() {
var listener = jest.genMockFn();
var listener = jest.fn();
var instance = <TestComponentWithReverseSpec listener={listener} />;
instance = ReactTestUtils.renderIntoDocument(instance);

View File

@@ -113,6 +113,10 @@ var ReactElement = function(type, key, ref, self, source, owner, props) {
return element;
};
/**
* Create and return a new ReactElement of the given type.
* See https://facebook.github.io/react/docs/top-level-api.html#react.createelement
*/
ReactElement.createElement = function(type, config, children) {
var propName;
@@ -126,6 +130,13 @@ ReactElement.createElement = function(type, config, children) {
if (config != null) {
if (__DEV__) {
warning(
/* eslint-disable no-proto */
config.__proto__ == null || config.__proto__ === Object.prototype,
/* eslint-enable no-proto */
'React.createElement(...): Expected props argument to be a plain object. ' +
'Properties defined in its prototype chain will be ignored.'
);
ref = !config.hasOwnProperty('ref') ||
Object.getOwnPropertyDescriptor(config, 'ref').get ? null : config.ref;
key = !config.hasOwnProperty('key') ||
@@ -223,6 +234,10 @@ ReactElement.createElement = function(type, config, children) {
);
};
/**
* Return a function that produces ReactElements of a given type.
* See https://facebook.github.io/react/docs/top-level-api.html#react.createfactory
*/
ReactElement.createFactory = function(type) {
var factory = ReactElement.createElement.bind(null, type);
// Expose the type on the factory and the prototype so that it can be
@@ -248,6 +263,10 @@ ReactElement.cloneAndReplaceKey = function(oldElement, newKey) {
return newElement;
};
/**
* Clone and return a new ReactElement using element as the starting point.
* See https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement
*/
ReactElement.cloneElement = function(element, config, children) {
var propName;
@@ -268,6 +287,15 @@ ReactElement.cloneElement = function(element, config, children) {
var owner = element._owner;
if (config != null) {
if (__DEV__) {
warning(
/* eslint-disable no-proto */
config.__proto__ == null || config.__proto__ === Object.prototype,
/* eslint-enable no-proto */
'React.cloneElement(...): Expected props argument to be a plain object. ' +
'Properties defined in its prototype chain will be ignored.'
);
}
if (config.ref !== undefined) {
// Silently steal the ref from the parent.
ref = config.ref;
@@ -319,6 +347,8 @@ ReactElement.cloneElement = function(element, config, children) {
};
/**
* Verifies the object is a ReactElement.
* See https://facebook.github.io/react/docs/top-level-api.html#react.isvalidelement
* @param {?object} object
* @return {boolean} True if `object` is a valid component.
* @final

View File

@@ -138,6 +138,18 @@ describe('ReactElement', function() {
expect(element.props.foo).toBe(1);
});
it('warns if the config object inherits from any type other than Object', function() {
spyOn(console, 'error');
React.createElement('div', {foo: 1});
expect(console.error).not.toHaveBeenCalled();
React.createElement('div', Object.create({foo: 1}));
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain(
'React.createElement(...): Expected props argument to be a plain object. ' +
'Properties defined in its prototype chain will be ignored.'
);
});
it('extracts key and ref from the config', function() {
var element = React.createFactory(ComponentClass)({
key: '12',

View File

@@ -66,6 +66,18 @@ describe('ReactElementClone', function() {
expect(ReactDOM.findDOMNode(component).childNodes[0].className).toBe('xyz');
});
it('should warn if the config object inherits from any type other than Object', function() {
spyOn(console, 'error');
React.cloneElement('div', {foo: 1});
expect(console.error).not.toHaveBeenCalled();
React.cloneElement('div', Object.create({foo: 1}));
expect(console.error.argsForCall.length).toBe(1);
expect(console.error.argsForCall[0][0]).toContain(
'React.cloneElement(...): Expected props argument to be a plain object. ' +
'Properties defined in its prototype chain will be ignored.'
);
});
it('should keep the original ref if it is not overridden', function() {
var Grandparent = React.createClass({
render: function() {

View File

@@ -1,505 +0,0 @@
/**
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule OrderedMap
*/
'use strict';
var invariant = require('invariant');
var PREFIX = 'key:';
/**
* Utility to extract a backing object from an initialization `Array`, allowing
* the caller to assist in resolving the unique ID for each entry via the
* `keyExtractor` callback. The `keyExtractor` must extract non-empty strings or
* numbers.
* @param {Array<Object!>} arr Array of items.
* @param {function} keyExtractor Extracts a unique key from each item.
* @return {Object} Map from unique key to originating value that the key was
* extracted from.
* @throws Exception if the initialization array has duplicate extracted keys.
*/
function extractObjectFromArray(arr, keyExtractor) {
var normalizedObj = {};
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
var key = keyExtractor(item);
assertValidPublicKey(key);
var normalizedKey = PREFIX + key;
invariant(
!(normalizedKey in normalizedObj),
'OrderedMap: IDs returned by the key extraction function must be unique.'
);
normalizedObj[normalizedKey] = item;
}
return normalizedObj;
}
/**
* Utility class for mappings with ordering. This class is to be used in an
* immutable manner. A `OrderedMap` is very much like the native JavaScript
* object, where keys map to values via the `get()` function. Also, like the
* native JavaScript object, there is an ordering associated with the mapping.
* This class is helpful because it eliminates many of the pitfalls that come
* with the native JavaScript ordered mappings. Specifically, there are
* inconsistencies with numeric keys in some JavaScript implementations
* (enumeration ordering). This class protects against those pitfalls and
* provides functional utilities for dealing with these `OrderedMap`s.
*
* - TODO:
* - orderedMergeExclusive: Merges mutually exclusive `OrderedMap`s.
* - mapReverse().
*
* @class {OrderedMap}
* @constructor {OrderedMap}
* @param {Object} normalizedObj Object that is known to be a defensive copy of
* caller supplied data. We require a defensive copy to guard against callers
* mutating. It is also assumed that the keys of `normalizedObj` have been
* normalized and do not contain any numeric-appearing strings.
* @param {number} computedLength The precomputed length of `_normalizedObj`
* keys.
* @private
*/
function OrderedMapImpl(normalizedObj, computedLength) {
this._normalizedObj = normalizedObj;
this._computedPositions = null;
this.length = computedLength;
}
/**
* Validates a "public" key - that is, one that the public facing API supplies.
* The key is then normalized for internal storage. In order to be considered
* valid, all keys must be non-empty, defined, non-null strings or numbers.
*
* @param {string?} key Validates that the key is suitable for use in a
* `OrderedMap`.
* @throws Error if key is not appropriate for use in `OrderedMap`.
*/
function assertValidPublicKey(key) {
invariant(
key !== '' && (typeof key === 'string' || typeof key === 'number'),
'OrderedMap: Key must be non-empty, non-null string or number.'
);
}
/**
* Validates that arguments to range operations are within the correct limits.
*
* @param {number} start Start of range.
* @param {number} length Length of range.
* @param {number} actualLen Actual length of range that should not be
* exceeded.
* @throws Error if range arguments are out of bounds.
*/
function assertValidRangeIndices(start, length, actualLen) {
invariant(
typeof start === 'number' &&
typeof length === 'number' &&
length >= 0 &&
start >= 0 &&
start + length <= actualLen,
'OrderedMap: `mapRange` and `forEachRange` expect non-negative start and ' +
'length arguments within the bounds of the instance.'
);
}
/**
* Merges two "normalized" objects (objects who's key have been normalized) into
* a `OrderedMap`.
*
* @param {Object} a Object of key value pairs.
* @param {Object} b Object of key value pairs.
* @return {OrderedMap} new `OrderedMap` that results in merging `a` and `b`.
*/
function _fromNormalizedObjects(a, b) {
// Second optional, both must be plain JavaScript objects.
invariant(
a && a.constructor === Object && (!b || b.constructor === Object),
'OrderedMap: Corrupted instance of OrderedMap detected.'
);
var newSet = {};
var length = 0;
var key;
for (key in a) {
if (a.hasOwnProperty(key)) {
newSet[key] = a[key];
length++;
}
}
for (key in b) {
if (b.hasOwnProperty(key)) {
// Increment length if not already added via first object (a)
if (!(key in newSet)) {
length++;
}
newSet[key] = b[key];
}
}
return new OrderedMapImpl(newSet, length);
}
/**
* Methods for `OrderedMap` instances.
*
* @lends OrderedMap.prototype
* TODO: Make this data structure lazy, unify with LazyArray.
* TODO: Unify this with ImmutableObject - it is to be used immutably.
* TODO: If so, consider providing `fromObject` API.
* TODO: Create faster implementation of merging/mapping from original Array,
* without having to first create an object - simply for the sake of merging.
*/
var OrderedMapMethods = {
/**
* Returns whether or not a given key is present in the map.
*
* @param {string} key Valid string key to lookup membership for.
* @return {boolean} Whether or not `key` is a member of the map.
* @throws Error if provided known invalid key.
*/
has: function(key) {
assertValidPublicKey(key);
var normalizedKey = PREFIX + key;
return normalizedKey in this._normalizedObj;
},
/**
* Returns the object for a given key, or `undefined` if not present. To
* distinguish an undefined entry vs not being in the set, use `has()`.
*
* @param {string} key String key to lookup the value for.
* @return {Object?} Object at key `key`, or undefined if not in map.
* @throws Error if provided known invalid key.
*/
get: function(key) {
assertValidPublicKey(key);
var normalizedKey = PREFIX + key;
return this.has(key) ? this._normalizedObj[normalizedKey] : undefined;
},
/**
* Merges, appending new keys to the end of the ordering. Keys in `orderedMap`
* that are redundant with `this`, maintain the same ordering index that they
* had in `this`. This is how standard JavaScript object merging would work.
* If you wish to prepend a `OrderedMap` to the beginning of another
* `OrderedMap` then simply reverse the order of operation. This is the analog
* to `merge(x, y)`.
*
* @param {OrderedMap} orderedMap OrderedMap to merge onto the end.
* @return {OrderedMap} New OrderedMap that represents the result of the
* merge.
*/
merge: function(orderedMap) {
invariant(
orderedMap instanceof OrderedMapImpl,
'OrderedMap.merge(...): Expected an OrderedMap instance.'
);
return _fromNormalizedObjects(
this._normalizedObj,
orderedMap._normalizedObj
);
},
/**
* Functional map API. Returns a new `OrderedMap`.
*
* @param {Function} cb Callback to invoke for each item.
* @param {Object?=} context Context to invoke callback from.
* @return {OrderedMap} OrderedMap that results from mapping.
*/
map: function(cb, context) {
return this.mapRange(cb, 0, this.length, context);
},
/**
* The callback `cb` is invoked with the arguments (item, key,
* indexInOriginal).
*
* @param {Function} cb Determines result for each item.
* @param {number} start Start index of map range.
* @param {end} length End index of map range.
* @param {*!?} context Context of callback invocation.
* @return {OrderedMap} OrderedMap resulting from mapping the range.
*/
mapRange: function(cb, start, length, context) {
var thisSet = this._normalizedObj;
var newSet = {};
var i = 0;
assertValidRangeIndices(start, length, this.length);
var end = start + length - 1;
for (var key in thisSet) {
if (thisSet.hasOwnProperty(key)) {
if (i >= start) {
if (i > end) {
break;
}
var item = thisSet[key];
newSet[key] = cb.call(context, item, key.substr(PREFIX.length), i);
}
i++;
}
}
return new OrderedMapImpl(newSet, length);
},
/**
* Function filter API. Returns new `OrderedMap`.
*
* @param {Function} cb Callback to invoke for each item.
* @param {Object?=} context Context to invoke callback from.
* @return {OrderedMap} OrderedMap that results from filtering.
*/
filter: function(cb, context) {
return this.filterRange(cb, 0, this.length, context);
},
/**
* The callback `cb` is invoked with the arguments (item, key,
* indexInOriginal).
*
* @param {Function} cb Returns true if item should be in result.
* @param {number} start Start index of filter range.
* @param {number} length End index of map range.
* @param {*!?} context Context of callback invocation.
* @return {OrderedMap} OrderedMap resulting from filtering the range.
*/
filterRange: function(cb, start, length, context) {
var newSet = {};
var newSetLength = 0;
this.forEachRange(function(item, key, originalIndex) {
if (cb.call(context, item, key, originalIndex)) {
var normalizedKey = PREFIX + key;
newSet[normalizedKey] = item;
newSetLength++;
}
}, start, length);
return new OrderedMapImpl(newSet, newSetLength);
},
forEach: function(cb, context) {
this.forEachRange(cb, 0, this.length, context);
},
forEachRange: function(cb, start, length, context) {
assertValidRangeIndices(start, length, this.length);
var thisSet = this._normalizedObj;
var i = 0;
var end = start + length - 1;
for (var key in thisSet) {
if (thisSet.hasOwnProperty(key)) {
if (i >= start) {
if (i > end) {
break;
}
var item = thisSet[key];
cb.call(context, item, key.substr(PREFIX.length), i);
}
i++;
}
}
},
/**
* Even though `mapRange`/`forEachKeyRange` allow zero length mappings, we'll
* impose an additional restriction here that the length of mapping be greater
* than zero - the only reason is that there are many ways to express length
* zero in terms of two keys and that is confusing.
*/
mapKeyRange: function(cb, startKey, endKey, context) {
var startIndex = this.indexOfKey(startKey);
var endIndex = this.indexOfKey(endKey);
invariant(
startIndex !== undefined && endIndex !== undefined,
'mapKeyRange must be given keys that are present.'
);
invariant(
endIndex >= startIndex,
'OrderedMap.mapKeyRange(...): `endKey` must not come before `startIndex`.'
);
return this.mapRange(cb, startIndex, (endIndex - startIndex) + 1, context);
},
forEachKeyRange: function(cb, startKey, endKey, context) {
var startIndex = this.indexOfKey(startKey);
var endIndex = this.indexOfKey(endKey);
invariant(
startIndex !== undefined && endIndex !== undefined,
'forEachKeyRange must be given keys that are present.'
);
invariant(
endIndex >= startIndex,
'OrderedMap.forEachKeyRange(...): `endKey` must not come before ' +
'`startIndex`.'
);
this.forEachRange(cb, startIndex, (endIndex - startIndex) + 1, context);
},
/**
* @param {number} pos Index to search for key at.
* @return {string|undefined} Either the key at index `pos` or undefined if
* not in map.
*/
keyAtIndex: function(pos) {
var computedPositions = this._getOrComputePositions();
var keyAtPos = computedPositions.keyByIndex[pos];
return keyAtPos ? keyAtPos.substr(PREFIX.length) : undefined;
},
/**
* @param {string} key String key from which to find the next key.
* @return {string|undefined} Either the next key, or undefined if there is no
* next key.
* @throws Error if `key` is not in this `OrderedMap`.
*/
keyAfter: function(key) {
return this.nthKeyAfter(key, 1);
},
/**
* @param {string} key String key from which to find the preceding key.
* @return {string|undefined} Either the preceding key, or undefined if there
* is no preceding.key.
* @throws Error if `key` is not in this `OrderedMap`.
*/
keyBefore: function(key) {
return this.nthKeyBefore(key, 1);
},
/**
* @param {string} key String key from which to find a following key.
* @param {number} n Distance to scan forward after `key`.
* @return {string|undefined} Either the nth key after `key`, or undefined if
* there is no next key.
* @throws Error if `key` is not in this `OrderedMap`.
*/
nthKeyAfter: function(key, n) {
var curIndex = this.indexOfKey(key);
invariant(
curIndex !== undefined,
'OrderedMap.nthKeyAfter: The key `%s` does not exist in this instance.',
key
);
return this.keyAtIndex(curIndex + n);
},
/**
* @param {string} key String key from which to find a preceding key.
* @param {number} n Distance to scan backwards before `key`.
* @return {string|undefined} Either the nth key before `key`, or undefined if
* there is no previous key.
* @throws Error if `key` is not in this `OrderedMap`.
*/
nthKeyBefore: function(key, n) {
return this.nthKeyAfter(key, -n);
},
/**
* @param {string} key Key to find the index of.
* @return {number|undefined} Index of the provided key, or `undefined` if the
* key is not found.
*/
indexOfKey: function(key) {
assertValidPublicKey(key);
var normalizedKey = PREFIX + key;
var computedPositions = this._getOrComputePositions();
var computedPosition = computedPositions.indexByKey[normalizedKey];
// Just writing it this way to make it clear this is intentional.
return computedPosition === undefined ? undefined : computedPosition;
},
/**
* @return {Array} An ordered array of this object's values.
*/
toArray: function() {
var result = [];
var thisSet = this._normalizedObj;
for (var key in thisSet) {
if (thisSet.hasOwnProperty(key)) {
result.push(thisSet[key]);
}
}
return result;
},
/**
* Finds the key at a given position, or indicates via `undefined` that that
* position does not exist in the `OrderedMap`. It is appropriate to return
* undefined, indicating that the key doesn't exist in the `OrderedMap`
* because `undefined` is not ever a valid `OrderedMap` key.
*
* @private
* @return {string?} Name of the item at position `pos`, or `undefined` if
* there is no item at that position.
*/
_getOrComputePositions: function() {
// TODO: Entertain computing this at construction time in some less
// performance critical paths.
var computedPositions = this._computedPositions;
if (!computedPositions) {
this._computePositions();
}
return this._computedPositions;
},
/**
* Precomputes the index/key mapping for future lookup. Since `OrderedMap`s
* are immutable, there is only ever a need to perform this once.
* @private
*/
_computePositions: function() {
this._computedPositions = {
keyByIndex: {},
indexByKey: {},
};
var keyByIndex = this._computedPositions.keyByIndex;
var indexByKey = this._computedPositions.indexByKey;
var index = 0;
var thisSet = this._normalizedObj;
for (var key in thisSet) {
if (thisSet.hasOwnProperty(key)) {
keyByIndex[index] = key;
indexByKey[key] = index;
index++;
}
}
},
};
Object.assign(OrderedMapImpl.prototype, OrderedMapMethods);
var OrderedMap = {
from: function(orderedMap) {
invariant(
orderedMap instanceof OrderedMapImpl,
'OrderedMap.from(...): Expected an OrderedMap instance.'
);
return _fromNormalizedObjects(orderedMap._normalizedObj, null);
},
fromArray: function(arr, keyExtractor) {
invariant(
Array.isArray(arr),
'OrderedMap.fromArray(...): First argument must be an array.'
);
invariant(
typeof keyExtractor === 'function',
'OrderedMap.fromArray(...): Second argument must be a function used ' +
'to determine the unique key for each entry.'
);
return new OrderedMapImpl(
extractObjectFromArray(arr, keyExtractor),
arr.length
);
},
};
module.exports = OrderedMap;

View File

@@ -1,107 +0,0 @@
/**
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactPropTransferer
*/
'use strict';
var emptyFunction = require('emptyFunction');
var joinClasses = require('joinClasses');
/**
* Creates a transfer strategy that will merge prop values using the supplied
* `mergeStrategy`. If a prop was previously unset, this just sets it.
*
* @param {function} mergeStrategy
* @return {function}
*/
function createTransferStrategy(mergeStrategy) {
return function(props, key, value) {
if (!props.hasOwnProperty(key)) {
props[key] = value;
} else {
props[key] = mergeStrategy(props[key], value);
}
};
}
var transferStrategyMerge = createTransferStrategy(function(a, b) {
// `merge` overrides the first object's (`props[key]` above) keys using the
// second object's (`value`) keys. An object's style's existing `propA` would
// get overridden. Flip the order here.
return Object.assign({}, b, a);
});
/**
* Transfer strategies dictate how props are transferred by `transferPropsTo`.
* NOTE: if you add any more exceptions to this list you should be sure to
* update `cloneWithProps()` accordingly.
*/
var TransferStrategies = {
/**
* Never transfer `children`.
*/
children: emptyFunction,
/**
* Transfer the `className` prop by merging them.
*/
className: createTransferStrategy(joinClasses),
/**
* Transfer the `style` prop (which is an object) by merging them.
*/
style: transferStrategyMerge,
};
/**
* Mutates the first argument by transferring the properties from the second
* argument.
*
* @param {object} props
* @param {object} newProps
* @return {object}
*/
function transferInto(props, newProps) {
for (var thisKey in newProps) {
if (!newProps.hasOwnProperty(thisKey)) {
continue;
}
var transferStrategy = TransferStrategies[thisKey];
if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) {
transferStrategy(props, thisKey, newProps[thisKey]);
} else if (!props.hasOwnProperty(thisKey)) {
props[thisKey] = newProps[thisKey];
}
}
return props;
}
/**
* ReactPropTransferer are capable of transferring props to another component
* using a `transferPropsTo` method.
*
* @class ReactPropTransferer
*/
var ReactPropTransferer = {
/**
* Merge two props objects using TransferStrategies.
*
* @param {object} oldProps original props (they take precedence)
* @param {object} newProps new props to merge in
* @return {object} a new object containing both sets of props merged.
*/
mergeProps: function(oldProps, newProps) {
return transferInto(Object.assign({}, oldProps), newProps);
},
};
module.exports = ReactPropTransferer;

View File

@@ -0,0 +1,163 @@
/**
* Copyright 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactComponentTreeDevtool
*/
'use strict';
var invariant = require('invariant');
var tree = {};
var rootIDs = [];
function updateTree(id, update) {
if (!tree[id]) {
tree[id] = {
parentID: null,
ownerID: null,
text: null,
childIDs: [],
displayName: 'Unknown',
isMounted: false,
updateCount: 0,
};
}
update(tree[id]);
}
function purgeDeep(id) {
var item = tree[id];
if (item) {
var {childIDs} = item;
delete tree[id];
childIDs.forEach(purgeDeep);
}
}
var ReactComponentTreeDevtool = {
onSetDisplayName(id, displayName) {
updateTree(id, item => item.displayName = displayName);
},
onSetChildren(id, nextChildIDs) {
updateTree(id, item => {
var prevChildIDs = item.childIDs;
item.childIDs = nextChildIDs;
nextChildIDs.forEach(nextChildID => {
var nextChild = tree[nextChildID];
invariant(
nextChild,
'Expected devtool events to fire for the child ' +
'before its parent includes it in onSetChildren().'
);
invariant(
nextChild.displayName != null,
'Expected onSetDisplayName() to fire for the child ' +
'before its parent includes it in onSetChildren().'
);
invariant(
nextChild.childIDs != null || nextChild.text != null,
'Expected onSetChildren() or onSetText() to fire for the child ' +
'before its parent includes it in onSetChildren().'
);
invariant(
nextChild.isMounted,
'Expected onMountComponent() to fire for the child ' +
'before its parent includes it in onSetChildren().'
);
if (prevChildIDs.indexOf(nextChildID) === -1) {
nextChild.parentID = id;
}
});
});
},
onSetOwner(id, ownerID) {
updateTree(id, item => item.ownerID = ownerID);
},
onSetText(id, text) {
updateTree(id, item => item.text = text);
},
onMountComponent(id) {
updateTree(id, item => item.isMounted = true);
},
onMountRootComponent(id) {
rootIDs.push(id);
},
onUpdateComponent(id) {
updateTree(id, item => item.updateCount++);
},
onUnmountComponent(id) {
updateTree(id, item => item.isMounted = false);
rootIDs = rootIDs.filter(rootID => rootID !== id);
},
purgeUnmountedComponents() {
if (ReactComponentTreeDevtool._preventPurging) {
// Should only be used for testing.
return;
}
Object.keys(tree)
.filter(id => !tree[id].isMounted)
.forEach(purgeDeep);
},
isMounted(id) {
var item = tree[id];
return item ? item.isMounted : false;
},
getChildIDs(id) {
var item = tree[id];
return item ? item.childIDs : [];
},
getDisplayName(id) {
var item = tree[id];
return item ? item.displayName : 'Unknown';
},
getOwnerID(id) {
var item = tree[id];
return item ? item.ownerID : null;
},
getParentID(id) {
var item = tree[id];
return item ? item.parentID : null;
},
getText(id) {
var item = tree[id];
return item ? item.text : null;
},
getUpdateCount(id) {
var item = tree[id];
return item ? item.updateCount : 0;
},
getRootIDs() {
return rootIDs;
},
getRegisteredIDs() {
return Object.keys(tree);
},
};
module.exports = ReactComponentTreeDevtool;

View File

@@ -0,0 +1,39 @@
/**
* Copyright 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactNativeOperationHistoryDevtool
*/
'use strict';
var history = [];
var ReactNativeOperationHistoryDevtool = {
onNativeOperation(debugID, type, payload) {
history.push({
instanceID: debugID,
type,
payload,
});
},
clearHistory() {
if (ReactNativeOperationHistoryDevtool._preventClearing) {
// Should only be used for tests.
return;
}
history = [];
},
getHistory() {
return history;
},
};
module.exports = ReactNativeOperationHistoryDevtool;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,724 @@
/**
* Copyright 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @emails react-core
*/
'use strict';
describe('ReactNativeOperationHistoryDevtool', () => {
var React;
var ReactDOM;
var ReactDOMComponentTree;
var ReactDOMFeatureFlags;
var ReactNativeOperationHistoryDevtool;
beforeEach(() => {
jest.resetModuleRegistry();
React = require('React');
ReactDOM = require('ReactDOM');
ReactDOMComponentTree = require('ReactDOMComponentTree');
ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
ReactNativeOperationHistoryDevtool = require('ReactNativeOperationHistoryDevtool');
});
function assertHistoryMatches(expectedHistory) {
var actualHistory = ReactNativeOperationHistoryDevtool.getHistory();
expect(actualHistory).toEqual(expectedHistory);
}
describe('mount', () => {
it('gets recorded for native roots', () => {
var node = document.createElement('div');
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div><p>Hi.</p></div>, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'mount',
payload: ReactDOMFeatureFlags.useCreateElement ?
'DIV' :
'<div data-reactroot="" data-reactid="1"><p data-reactid="2">Hi.</p></div>',
}]);
});
it('gets recorded for composite roots', () => {
function Foo() {
return <div><p>Hi.</p></div>;
}
var node = document.createElement('div');
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<Foo />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'mount',
payload: ReactDOMFeatureFlags.useCreateElement ?
'DIV' :
'<div data-reactroot="" data-reactid="1">' +
'<p data-reactid="2">Hi.</p></div>',
}]);
});
it('gets ignored for composite roots that return null', () => {
function Foo() {
return null;
}
var node = document.createElement('div');
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<Foo />, node);
// Empty DOM components should be invisible to devtools.
assertHistoryMatches([]);
});
it('gets recorded when a native is mounted deeply instead of null', () => {
var element;
function Foo() {
return element;
}
ReactNativeOperationHistoryDevtool._preventClearing = true;
var node = document.createElement('div');
element = null;
ReactDOM.render(<Foo />, node);
element = <span />;
ReactDOM.render(<Foo />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
// Since empty components should be invisible to devtools,
// we record a "mount" event rather than a "replace with".
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'mount',
payload: 'SPAN',
}]);
});
});
describe('update styles', () => {
it('gets recorded during mount', () => {
var node = document.createElement('div');
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div style={{
color: 'red',
backgroundColor: 'yellow',
}} />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
if (ReactDOMFeatureFlags.useCreateElement) {
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update styles',
payload: {
color: 'red',
backgroundColor: 'yellow',
},
}, {
instanceID: inst._debugID,
type: 'mount',
payload: 'DIV',
}]);
} else {
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'mount',
payload: '<div style="color:red;background-color:yellow;" ' +
'data-reactroot="" data-reactid="1"></div>',
}]);
}
});
it('gets recorded during an update', () => {
var node = document.createElement('div');
ReactDOM.render(<div />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div style={{ color: 'red' }} />, node);
ReactDOM.render(<div style={{
color: 'blue',
backgroundColor: 'yellow',
}} />, node);
ReactDOM.render(<div style={{ backgroundColor: 'green' }} />, node);
ReactDOM.render(<div />, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update styles',
payload: { color: 'red' },
}, {
instanceID: inst._debugID,
type: 'update styles',
payload: { color: 'blue', backgroundColor: 'yellow' },
}, {
instanceID: inst._debugID,
type: 'update styles',
payload: { color: '', backgroundColor: 'green' },
}, {
instanceID: inst._debugID,
type: 'update styles',
payload: { backgroundColor: '' },
}]);
});
it('gets ignored if the styles are shallowly equal', () => {
var node = document.createElement('div');
ReactDOM.render(<div />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div style={{
color: 'red',
backgroundColor: 'yellow',
}} />, node);
ReactDOM.render(<div style={{
color: 'red',
backgroundColor: 'yellow',
}} />, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update styles',
payload: {
color: 'red',
backgroundColor: 'yellow',
},
}]);
});
});
describe('update attribute', () => {
describe('simple attribute', () => {
it('gets recorded during mount', () => {
var node = document.createElement('div');
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div className="rad" tabIndex={42} />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
if (ReactDOMFeatureFlags.useCreateElement) {
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update attribute',
payload: { className: 'rad' },
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { tabIndex: 42 },
}, {
instanceID: inst._debugID,
type: 'mount',
payload: 'DIV',
}]);
} else {
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'mount',
payload: '<div class="rad" tabindex="42" data-reactroot="" ' +
'data-reactid="1"></div>',
}]);
}
});
it('gets recorded during an update', () => {
var node = document.createElement('div');
ReactDOM.render(<div />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div className="rad" />, node);
ReactDOM.render(<div className="mad" tabIndex={42} />, node);
ReactDOM.render(<div tabIndex={43} />, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update attribute',
payload: { className: 'rad' },
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { className: 'mad' },
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { tabIndex: 42 },
}, {
instanceID: inst._debugID,
type: 'remove attribute',
payload: 'className',
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { tabIndex: 43 },
}]);
});
});
describe('attribute that gets removed with certain values', () => {
it('gets recorded as a removal during an update', () => {
var node = document.createElement('div');
ReactDOM.render(<div />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div disabled={true} />, node);
ReactDOM.render(<div disabled={false} />, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update attribute',
payload: { disabled: true },
}, {
instanceID: inst._debugID,
type: 'remove attribute',
payload: 'disabled',
}]);
});
});
describe('custom attribute', () => {
it('gets recorded during mount', () => {
var node = document.createElement('div');
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div data-x="rad" data-y={42} />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
if (ReactDOMFeatureFlags.useCreateElement) {
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update attribute',
payload: { 'data-x': 'rad' },
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { 'data-y': 42 },
}, {
instanceID: inst._debugID,
type: 'mount',
payload: 'DIV',
}]);
} else {
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'mount',
payload: '<div data-x="rad" data-y="42" data-reactroot="" ' +
'data-reactid="1"></div>',
}]);
}
});
it('gets recorded during an update', () => {
var node = document.createElement('div');
ReactDOM.render(<div />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div data-x="rad" />, node);
ReactDOM.render(<div data-x="mad" data-y={42} />, node);
ReactDOM.render(<div data-y={43} />, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update attribute',
payload: { 'data-x': 'rad' },
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { 'data-x': 'mad' },
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { 'data-y': 42 },
}, {
instanceID: inst._debugID,
type: 'remove attribute',
payload: 'data-x',
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { 'data-y': 43 },
}]);
});
});
describe('attribute on a web component', () => {
it('gets recorded during mount', () => {
var node = document.createElement('div');
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<my-component className="rad" tabIndex={42} />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
if (ReactDOMFeatureFlags.useCreateElement) {
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update attribute',
payload: { className: 'rad' },
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { tabIndex: 42 },
}, {
instanceID: inst._debugID,
type: 'mount',
payload: 'MY-COMPONENT',
}]);
} else {
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'mount',
payload: '<my-component className="rad" tabIndex="42" ' +
'data-reactroot="" data-reactid="1"></my-component>',
}]);
}
});
it('gets recorded during an update', () => {
var node = document.createElement('div');
ReactDOM.render(<my-component />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<my-component className="rad" />, node);
ReactDOM.render(<my-component className="mad" tabIndex={42} />, node);
ReactDOM.render(<my-component tabIndex={43} />, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'update attribute',
payload: { className: 'rad' },
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { className: 'mad' },
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { tabIndex: 42 },
}, {
instanceID: inst._debugID,
type: 'remove attribute',
payload: 'className',
}, {
instanceID: inst._debugID,
type: 'update attribute',
payload: { tabIndex: 43 },
}]);
});
});
});
describe('replace text', () => {
describe('text content', () => {
it('gets recorded during an update from text content', () => {
var node = document.createElement('div');
ReactDOM.render(<div>Hi.</div>, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div>Bye.</div>, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'replace text',
payload: 'Bye.',
}]);
});
it('gets recorded during an update from html', () => {
var node = document.createElement('div');
ReactDOM.render(<div dangerouslySetInnerHTML={{__html: 'Hi.'}} />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div>Bye.</div>, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'replace text',
payload: 'Bye.',
}]);
});
it('gets recorded during an update from children', () => {
var node = document.createElement('div');
ReactDOM.render(<div><span /><p /></div>, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div>Bye.</div>, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'remove child',
payload: {fromIndex: 0},
}, {
instanceID: inst._debugID,
type: 'remove child',
payload: {fromIndex: 1},
}, {
instanceID: inst._debugID,
type: 'replace text',
payload: 'Bye.',
}]);
});
it('gets ignored if new text is equal', () => {
var node = document.createElement('div');
ReactDOM.render(<div>Hi.</div>, node);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div>Hi.</div>, node);
assertHistoryMatches([]);
});
});
describe('text node', () => {
it('gets recorded during an update', () => {
var node = document.createElement('div');
ReactDOM.render(<div>{'Hi.'}{42}</div>, node);
var inst1 = ReactDOMComponentTree.getInstanceFromNode(node.firstChild.childNodes[0]);
var inst2 = ReactDOMComponentTree.getInstanceFromNode(node.firstChild.childNodes[3]);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div>{'Bye.'}{43}</div>, node);
assertHistoryMatches([{
instanceID: inst1._debugID,
type: 'replace text',
payload: 'Bye.',
}, {
instanceID: inst2._debugID,
type: 'replace text',
payload: '43',
}]);
});
it('gets ignored if new text is equal', () => {
var node = document.createElement('div');
ReactDOM.render(<div>{'Hi.'}{42}</div>, node);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div>{'Hi.'}{42}</div>, node);
assertHistoryMatches([]);
});
});
});
describe('replace with', () => {
it('gets recorded when composite renders to a different type', () => {
var element;
function Foo() {
return element;
}
var node = document.createElement('div');
element = <div />;
ReactDOM.render(<Foo />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
element = <span />;
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<Foo />, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'replace with',
payload: 'SPAN',
}]);
});
it('gets recorded when composite renders to null after a native', () => {
var element;
function Foo() {
return element;
}
var node = document.createElement('div');
element = <span />;
ReactDOM.render(<Foo />, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
element = null;
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<Foo />, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'replace with',
payload: '#comment',
}]);
});
it('gets ignored if the type has not changed', () => {
var element;
function Foo() {
return element;
}
var node = document.createElement('div');
element = <div />;
ReactDOM.render(<Foo />, node);
element = <div />;
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<Foo />, node);
assertHistoryMatches([]);
});
});
describe('replace children', () => {
it('gets recorded during an update from text content', () => {
var node = document.createElement('div');
ReactDOM.render(<div>Hi.</div>, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(
<div dangerouslySetInnerHTML={{__html: 'Bye.'}} />,
node
);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'replace children',
payload: 'Bye.',
}]);
});
it('gets recorded during an update from html', () => {
var node = document.createElement('div');
ReactDOM.render(
<div dangerouslySetInnerHTML={{__html: 'Hi.'}} />,
node
);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(
<div dangerouslySetInnerHTML={{__html: 'Bye.'}} />,
node
);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'replace children',
payload: 'Bye.',
}]);
});
it('gets recorded during an update from children', () => {
var node = document.createElement('div');
ReactDOM.render(<div><span /><p /></div>, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(
<div dangerouslySetInnerHTML={{__html: 'Hi.'}} />,
node
);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'remove child',
payload: {fromIndex: 0},
}, {
instanceID: inst._debugID,
type: 'remove child',
payload: {fromIndex: 1},
}, {
instanceID: inst._debugID,
type: 'replace children',
payload: 'Hi.',
}]);
});
it('gets ignored if new html is equal', () => {
var node = document.createElement('div');
ReactDOM.render(
<div dangerouslySetInnerHTML={{__html: 'Hi.'}} />,
node
);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(
<div dangerouslySetInnerHTML={{__html: 'Hi.'}} />,
node
);
assertHistoryMatches([]);
});
});
describe('insert child', () => {
it('gets reported when a child is inserted', () => {
var node = document.createElement('div');
ReactDOM.render(<div><span /></div>, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div><span /><p /></div>, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'insert child',
payload: {toIndex: 1, content: 'P'},
}]);
});
});
describe('move child', () => {
it('gets reported when a child is inserted', () => {
var node = document.createElement('div');
ReactDOM.render(<div><span key="a" /><p key="b" /></div>, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div><p key="b" /><span key="a" /></div>, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'move child',
payload: {fromIndex: 0, toIndex: 1},
}]);
});
});
describe('remove child', () => {
it('gets reported when a child is removed', () => {
var node = document.createElement('div');
ReactDOM.render(<div><span key="a" /><p key="b" /></div>, node);
var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
ReactNativeOperationHistoryDevtool._preventClearing = true;
ReactDOM.render(<div><span key="a" /></div>, node);
assertHistoryMatches([{
instanceID: inst._debugID,
type: 'remove child',
payload: {fromIndex: 1},
}]);
});
});
});

View File

@@ -1,5 +1,5 @@
{
"name": "react-haste",
"version": "15.0.0-rc.2",
"version": "15.0.1",
"license": "BSD-3-Clause"
}

View File

@@ -16,7 +16,6 @@
var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactDefaultInjection = require('ReactDefaultInjection');
var ReactMount = require('ReactMount');
var ReactPerf = require('ReactPerf');
var ReactReconciler = require('ReactReconciler');
var ReactUpdates = require('ReactUpdates');
var ReactVersion = require('ReactVersion');
@@ -28,11 +27,9 @@ var warning = require('warning');
ReactDefaultInjection.inject();
var render = ReactPerf.measure('React', 'render', ReactMount.render);
var React = {
findDOMNode: findDOMNode,
render: render,
render: ReactMount.render,
unmountComponentAtNode: ReactMount.unmountComponentAtNode,
version: ReactVersion,

View File

@@ -13,7 +13,6 @@
var DOMChildrenOperations = require('DOMChildrenOperations');
var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactPerf = require('ReactPerf');
/**
* Operations used to process updates to DOM nodes.
@@ -32,8 +31,4 @@ var ReactDOMIDOperations = {
},
};
ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', {
dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates',
});
module.exports = ReactDOMIDOperations;

View File

@@ -22,7 +22,6 @@ var ReactElement = require('ReactElement');
var ReactFeatureFlags = require('ReactFeatureFlags');
var ReactInstrumentation = require('ReactInstrumentation');
var ReactMarkupChecksum = require('ReactMarkupChecksum');
var ReactPerf = require('ReactPerf');
var ReactReconciler = require('ReactReconciler');
var ReactUpdateQueue = require('ReactUpdateQueue');
var ReactUpdates = require('ReactUpdates');
@@ -308,6 +307,10 @@ var ReactMount = {
shouldReuseMarkup,
context
) {
if (__DEV__) {
ReactInstrumentation.debugTool.onBeginFlush();
}
// Various parts of our code (such as ReactCompositeComponent's
// _renderValidatedComponent) assume that calls to render aren't nested;
// verify that that's the case.
@@ -333,6 +336,12 @@ var ReactMount = {
ReactBrowserEventEmitter.ensureScrollValueMonitoring();
var componentInstance = instantiateReactComponent(nextElement);
if (__DEV__) {
// Mute future events from the top level wrapper.
// It is an implementation detail that devtools should not know about.
componentInstance._debugID = 0;
}
// The initial render is synchronous but any updates that happen during
// rendering, in componentWillMount or componentDidMount, will be batched
// according to the current batching strategy.
@@ -349,7 +358,11 @@ var ReactMount = {
instancesByReactRootID[wrapperID] = componentInstance;
if (__DEV__) {
ReactInstrumentation.debugTool.onMountRootComponent(componentInstance);
// The instance here is TopLevelWrapper so we report mount for its child.
ReactInstrumentation.debugTool.onMountRootComponent(
componentInstance._renderedComponent._debugID
);
ReactInstrumentation.debugTool.onEndFlush();
}
return componentInstance;
@@ -497,6 +510,7 @@ var ReactMount = {
/**
* Renders a React component into the DOM in the supplied `container`.
* See https://facebook.github.io/react/docs/top-level-api.html#reactdom.render
*
* 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
@@ -513,6 +527,7 @@ var ReactMount = {
/**
* Unmounts and destroys the React component rendered in the `container`.
* See https://facebook.github.io/react/docs/top-level-api.html#reactdom.unmountcomponentatnode
*
* @param {DOMElement} container DOM element containing a React component.
* @return {boolean} True if a component was found in and unmounted from
@@ -684,12 +699,18 @@ var ReactMount = {
setInnerHTML(container, markup);
ReactDOMComponentTree.precacheNode(instance, container.firstChild);
}
if (__DEV__) {
var nativeNode = ReactDOMComponentTree.getInstanceFromNode(container.firstChild);
if (nativeNode._debugID !== 0) {
ReactInstrumentation.debugTool.onNativeOperation(
nativeNode._debugID,
'mount',
markup.toString()
);
}
}
},
};
ReactPerf.measureMethods(ReactMount, 'ReactMount', {
_renderNewRootComponent: '_renderNewRootComponent',
_mountImageIntoNode: '_mountImageIntoNode',
});
module.exports = ReactMount;

View File

@@ -35,7 +35,7 @@ var recordIDAndReturnFalse = function(id, event) {
recordID(id);
return false;
};
var LISTENER = jest.genMockFn();
var LISTENER = jest.fn();
var ON_CLICK_KEY = keyOf({onClick: null});
var ON_TOUCH_TAP_KEY = keyOf({onTouchTap: null});
var ON_CHANGE_KEY = keyOf({onChange: null});
@@ -284,7 +284,7 @@ describe('ReactBrowserEventEmitter', function() {
*/
it('should invoke handlers that were removed while bubbling', function() {
var handleParentClick = jest.genMockFn();
var handleParentClick = jest.fn();
var handleChildClick = function(event) {
EventPluginHub.deleteAllListeners(getInternal(PARENT));
};
@@ -303,7 +303,7 @@ describe('ReactBrowserEventEmitter', function() {
});
it('should not invoke newly inserted handlers while bubbling', function() {
var handleParentClick = jest.genMockFn();
var handleParentClick = jest.fn();
var handleChildClick = function(event) {
EventPluginHub.putListener(
getInternal(PARENT),

Some files were not shown because too many files have changed in this diff Show More