Compare commits
258 Commits
pr33512
...
0.14-stabl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
894d20744c | ||
|
|
e1208624eb | ||
|
|
66fff86415 | ||
|
|
c2c15cc970 | ||
|
|
e40a12073d | ||
|
|
62e1177d77 | ||
|
|
8f1def2f32 | ||
|
|
5ffc169585 | ||
|
|
1aa2064b48 | ||
|
|
1aee28ef1b | ||
|
|
27e2d6e31f | ||
|
|
d58718fe01 | ||
|
|
15a8fc105f | ||
|
|
da0beaf179 | ||
|
|
89ca6df46b | ||
|
|
57a4c1d597 | ||
|
|
56e9ce8c91 | ||
|
|
6a072b3f81 | ||
|
|
5d7f398ca8 | ||
|
|
fe3cfcd3b2 | ||
|
|
6a87954262 | ||
|
|
4ccf18b9a0 | ||
|
|
4a9e52efb4 | ||
|
|
82982f6dab | ||
|
|
a7321487c9 | ||
|
|
3e1a2f18f6 | ||
|
|
c3b7f937b0 | ||
|
|
5bed1f3d3c | ||
|
|
c0993bf1a8 | ||
|
|
19953781e4 | ||
|
|
dad9991a75 | ||
|
|
d824d0d03b | ||
|
|
4c4bfba2c3 | ||
|
|
b17b2ea3f6 | ||
|
|
25fdaf95be | ||
|
|
5f7f9b1552 | ||
|
|
3ff62fa9d1 | ||
|
|
95d310cad2 | ||
|
|
c03a057f9a | ||
|
|
1b2286e933 | ||
|
|
6bde147f3e | ||
|
|
1e065c89c9 | ||
|
|
103074f4cc | ||
|
|
23b1f97aaa | ||
|
|
e01bac801f | ||
|
|
4bba4207ee | ||
|
|
9ce4be4430 | ||
|
|
d68bead611 | ||
|
|
9479256e7e | ||
|
|
9e821ee60a | ||
|
|
c585396f2e | ||
|
|
cd654486f8 | ||
|
|
84e099c3af | ||
|
|
2152045b44 | ||
|
|
200dcdad0a | ||
|
|
5730beca2b | ||
|
|
3888b47da4 | ||
|
|
4226ee589d | ||
|
|
e48343bd03 | ||
|
|
88543cec19 | ||
|
|
741124548d | ||
|
|
05acd8ed35 | ||
|
|
8fb9daa5ed | ||
|
|
2f77642b9f | ||
|
|
49617c3be7 | ||
|
|
3285d83440 | ||
|
|
decfbdf1f5 | ||
|
|
79732f04bf | ||
|
|
b797075c63 | ||
|
|
44f1a9a262 | ||
|
|
4ecc10880e | ||
|
|
5189deb5ee | ||
|
|
9adfb08868 | ||
|
|
f5dd3e7cf6 | ||
|
|
da3c9527c5 | ||
|
|
2a1dc07046 | ||
|
|
8c27faab7a | ||
|
|
9e380c2679 | ||
|
|
7594b977d6 | ||
|
|
a808423626 | ||
|
|
ecd2da90e5 | ||
|
|
60afae7ca5 | ||
|
|
381fe0b3e6 | ||
|
|
2f21dc6f76 | ||
|
|
e45c534f6d | ||
|
|
76aa60db91 | ||
|
|
4206fd1dce | ||
|
|
d590910f6d | ||
|
|
cf17f3291f | ||
|
|
5879799f8e | ||
|
|
80cadc6f66 | ||
|
|
44e90c040d | ||
|
|
d5bf8c553f | ||
|
|
e278ce4445 | ||
|
|
06cad05d49 | ||
|
|
f305deb065 | ||
|
|
9c091afe74 | ||
|
|
fb6b3b05f4 | ||
|
|
575cf6a82e | ||
|
|
d6a0a083e4 | ||
|
|
e7b178390d | ||
|
|
a9732ba548 | ||
|
|
05269bf16b | ||
|
|
093a97c54b | ||
|
|
0d5d0b2688 | ||
|
|
c8398491d8 | ||
|
|
149613d065 | ||
|
|
0516e74473 | ||
|
|
3f355d99c5 | ||
|
|
a29b4938a8 | ||
|
|
142059d294 | ||
|
|
d2dde00940 | ||
|
|
d9bf86e83a | ||
|
|
527d7b154b | ||
|
|
f8777eea9e | ||
|
|
6dd8427c20 | ||
|
|
33cae8c9b1 | ||
|
|
881d023c0e | ||
|
|
926378cacb | ||
|
|
343109e248 | ||
|
|
5fd421c996 | ||
|
|
1f1a127891 | ||
|
|
7bb2119733 | ||
|
|
a4ad2b4e54 | ||
|
|
050b8f1875 | ||
|
|
821104185e | ||
|
|
dc5411c795 | ||
|
|
a1decaf2a5 | ||
|
|
b6dc8681bb | ||
|
|
4588820073 | ||
|
|
852a63fe23 | ||
|
|
617cfdd434 | ||
|
|
85c09e5507 | ||
|
|
235b914797 | ||
|
|
9ed0fdb850 | ||
|
|
e2e04fdbc3 | ||
|
|
1f41a53d1e | ||
|
|
3ef0838567 | ||
|
|
319a266941 | ||
|
|
d5f312866b | ||
|
|
2c5dadb0c5 | ||
|
|
0f7fad10d6 | ||
|
|
da7b9043a4 | ||
|
|
cc92028f11 | ||
|
|
969014c832 | ||
|
|
b335180686 | ||
|
|
33717bc425 | ||
|
|
9921659616 | ||
|
|
f974581a6a | ||
|
|
ef20f03429 | ||
|
|
1eed5b0e10 | ||
|
|
934d5b642e | ||
|
|
40e4655a5e | ||
|
|
789a9b70cb | ||
|
|
3a793ba27b | ||
|
|
3f2f763dea | ||
|
|
c389c1def5 | ||
|
|
1cef6ebabf | ||
|
|
f92a630737 | ||
|
|
55b6839684 | ||
|
|
e6f8ad33cf | ||
|
|
c806ed1128 | ||
|
|
294b50a695 | ||
|
|
22c9562cd9 | ||
|
|
cde2de3ce7 | ||
|
|
061725c9b6 | ||
|
|
ed11bdc5bf | ||
|
|
319c5c4453 | ||
|
|
19678baa1a | ||
|
|
a43dfdc33d | ||
|
|
9265032a12 | ||
|
|
36db2aeeb0 | ||
|
|
ca8ad7ff8e | ||
|
|
30ec56a027 | ||
|
|
5e9f00a4b6 | ||
|
|
a23bab0cf5 | ||
|
|
6bf6beb2d2 | ||
|
|
c796629e66 | ||
|
|
3eed5deead | ||
|
|
3b97d5e30c | ||
|
|
fd05a6ee7d | ||
|
|
17761fae9b | ||
|
|
34bb99b07f | ||
|
|
4fda3eb9da | ||
|
|
c6c3c0e255 | ||
|
|
807c555c77 | ||
|
|
fdf6f6bbb0 | ||
|
|
5a2312c8e5 | ||
|
|
01622a4442 | ||
|
|
a4fd08973b | ||
|
|
c2dd57c6a6 | ||
|
|
db23e49467 | ||
|
|
3117584e0e | ||
|
|
26258313cd | ||
|
|
d602f1d3fb | ||
|
|
c181b824ca | ||
|
|
d6100a703f | ||
|
|
afef42e377 | ||
|
|
24059873ac | ||
|
|
bac2462dd5 | ||
|
|
878482154e | ||
|
|
bfba064631 | ||
|
|
0f6a151650 | ||
|
|
f0782e2b2e | ||
|
|
b247f68b33 | ||
|
|
6e2450e8f2 | ||
|
|
c2dde8df0b | ||
|
|
aaf8f870cb | ||
|
|
4952cd00d4 | ||
|
|
eadbf33296 | ||
|
|
12cafa7e00 | ||
|
|
090c2dd833 | ||
|
|
c469697ad7 | ||
|
|
d8a9cd365c | ||
|
|
6323f03148 | ||
|
|
6384e56d8d | ||
|
|
84f6915315 | ||
|
|
fdb2486b98 | ||
|
|
fb620be2b8 | ||
|
|
0acdefb7cc | ||
|
|
e0f74c6c6c | ||
|
|
8ab0651158 | ||
|
|
712c6cb1d8 | ||
|
|
e931e02a36 | ||
|
|
6c84e3d410 | ||
|
|
e8b5c75c0f | ||
|
|
b5524faa4b | ||
|
|
411726dcf1 | ||
|
|
28f242d0b4 | ||
|
|
5cc9abfe60 | ||
|
|
348a37cc99 | ||
|
|
bed6aefc46 | ||
|
|
1e175d0858 | ||
|
|
193e4cf582 | ||
|
|
b0aa296519 | ||
|
|
b020e69edc | ||
|
|
d69657bca4 | ||
|
|
8812c6b678 | ||
|
|
60e30f1da4 | ||
|
|
e4300d951c | ||
|
|
13f3cdeeb1 | ||
|
|
fe085c1cce | ||
|
|
b71499e5f4 | ||
|
|
df0dac72c2 | ||
|
|
5f2a80c086 | ||
|
|
e21f1c7759 | ||
|
|
21588d900f | ||
|
|
5039dad053 | ||
|
|
b120cdafb2 | ||
|
|
f93bb3aa6a | ||
|
|
ac2853b5d4 | ||
|
|
007cf55872 | ||
|
|
ec7947979b | ||
|
|
24f7659b7c | ||
|
|
c2443c227c | ||
|
|
3603d45157 | ||
|
|
0811e63e22 | ||
|
|
3917c04f16 |
@@ -16,4 +16,4 @@ packages/react-codemod/test/
|
||||
packages/react-codemod/scripts/
|
||||
packages/react-codemod/build/
|
||||
packages/react-codemod/node_modules/
|
||||
vendor/react-dom.js
|
||||
vendor/*
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -24,3 +24,4 @@ chrome-user-data
|
||||
*.sublime-workspace
|
||||
.idea
|
||||
*.iml
|
||||
.vscode
|
||||
|
||||
@@ -54,6 +54,8 @@ script:
|
||||
-F "react-with-addons.min=@build/react-with-addons.min.js" \
|
||||
-F "react-dom=@build/react-dom.js" \
|
||||
-F "react-dom.min=@build/react-dom.min.js" \
|
||||
-F "react-dom-server=@build/react-dom-server.js" \
|
||||
-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 "commit=$TRAVIS_COMMIT" \
|
||||
|
||||
159
CHANGELOG.md
159
CHANGELOG.md
@@ -1,3 +1,162 @@
|
||||
## 0.14.8 (March 29, 2016)
|
||||
|
||||
### React
|
||||
- Fixed memory leak when rendering on the server
|
||||
|
||||
## 0.14.7 (January 28, 2016)
|
||||
|
||||
### React
|
||||
- Fixed bug with `<option>` tags when using `dangerouslySetInnerHTML`
|
||||
- Fixed memory leak in synthetic event system
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Fixed bug with calling `setState` in `componentWillMount` when using shallow rendering
|
||||
|
||||
|
||||
## 0.14.6 (January 6, 2016)
|
||||
|
||||
### React
|
||||
- Updated `fbjs` dependency to pick up change affecting handling of undefined document.
|
||||
|
||||
|
||||
## 0.14.5 (December 29, 2015)
|
||||
|
||||
### React
|
||||
- More minor internal changes for better compatibility with React Native
|
||||
|
||||
|
||||
## 0.14.4 (December 29, 2015)
|
||||
|
||||
### React
|
||||
- Minor internal changes for better compatibility with React Native
|
||||
|
||||
### React DOM
|
||||
- The `autoCapitalize` and `autoCorrect` props are now set as attributes in the DOM instead of properties to improve cross-browser compatibility
|
||||
- Fixed bug with controlled `<select>` elements not handling updates properly
|
||||
|
||||
### React Perf Add-on
|
||||
- Some DOM operation names have been updated for clarity in the output of `.printDOM()`
|
||||
|
||||
|
||||
## 0.14.3 (November 18, 2015)
|
||||
|
||||
### React DOM
|
||||
- Added support for `nonce` attribute for `<script>` and `<style>` elements
|
||||
- Added support for `reversed` attribute for `<ol>` elements
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Fixed bug with shallow rendering and function refs
|
||||
|
||||
### React CSSTransitionGroup Add-on
|
||||
- Fixed bug resulting in timeouts firing incorrectly when mounting and unmounting rapidly
|
||||
|
||||
### React on Bower
|
||||
- Added `react-dom-server.js` to expose `renderToString` and `renderToStaticMarkup` for usage in the browser
|
||||
|
||||
|
||||
## 0.14.2 (November 2, 2015)
|
||||
|
||||
### React DOM
|
||||
- Fixed bug with development build preventing events from firing in some versions of Internet Explorer & Edge
|
||||
- Fixed bug with development build when using es5-sham in older versions of Internet Explorer
|
||||
- Added support for `integrity` attribute
|
||||
- Fixed bug resulting in `children` prop being coerced to a string for custom elements, which was not the desired behavior
|
||||
- Moved `react` from `dependencies` to `peerDependencies` to match expectations and align with `react-addons-*` packages
|
||||
|
||||
|
||||
## 0.14.1 (October 28, 2015)
|
||||
|
||||
### React DOM
|
||||
- Fixed bug where events wouldn't fire in old browsers when using React in development mode
|
||||
- Fixed bug preventing use of `dangerouslySetInnerHTML` with Closure Compiler Advanced mode
|
||||
- Added support for `srcLang`, `default`, and `kind` attributes for `<track>` elements
|
||||
- Added support for `color` attribute
|
||||
- Ensured legacy `.props` access on DOM nodes is updated on re-renders
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Fixed `scryRenderedDOMComponentsWithClass` so it works with SVG
|
||||
|
||||
### React CSSTransitionGroup Add-on
|
||||
- Fix bug preventing `0` to be used as a timeout value
|
||||
|
||||
### React on Bower
|
||||
- Added `react-dom.js` to `main` to improve compatibility with tooling
|
||||
|
||||
|
||||
## 0.14.0 (October 7, 2015)
|
||||
|
||||
### 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`).
|
||||
- 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.**
|
||||
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- `React.initializeTouchEvents` is no longer necessary and has been removed completely. Touch events now work automatically.
|
||||
- Add-Ons: Due to the DOM node refs change mentioned above, `TestUtils.findAllInRenderedTree` and related helpers are no longer able to take a DOM component, only a custom component.
|
||||
- The `props` object is now frozen, so mutating props after creating a component element is no longer supported. In most cases, [`React.cloneElement`](/react/docs/top-level-api.html#react.cloneelement) should be used instead. This change makes your components easier to reason about and enables the compiler optimizations mentioned above.
|
||||
- Plain objects are no longer supported as React children; arrays should be used instead. You can use the [`createFragment`](/react/docs/create-fragment.html) helper to migrate, which now returns an array.
|
||||
- Add-Ons: `classSet` has been removed. Use [classnames](https://github.com/JedWatson/classnames) instead.
|
||||
- Web components (custom elements) now use native property names. Eg: `class` instead of `className`.
|
||||
|
||||
### Deprecations
|
||||
|
||||
- `this.getDOMNode()` is now deprecated and `ReactDOM.findDOMNode(this)` can be used instead. Note that in the common case, `findDOMNode` is now unnecessary since a ref to the DOM component is now the actual DOM node.
|
||||
- `setProps` and `replaceProps` are now deprecated. Instead, call ReactDOM.render again at the top level with the new props.
|
||||
- ES6 component classes must now extend `React.Component` in order to enable stateless function components. The [ES3 module pattern](/react/blog/2015/01/27/react-v0.13.0-beta-1.html#other-languages) will continue to work.
|
||||
- Reusing and mutating a `style` object between renders has been deprecated. This mirrors our change to freeze the `props` object.
|
||||
- Add-Ons: `cloneWithProps` is now deprecated. Use [`React.cloneElement`](/react/docs/top-level-api.html#react.cloneelement) instead (unlike `cloneWithProps`, `cloneElement` does not merge `className` or `style` automatically; you can merge them manually if needed).
|
||||
- Add-Ons: To improve reliability, `CSSTransitionGroup` will no longer listen to transition events. Instead, you should specify transition durations manually using props such as `transitionEnterTimeout={500}`.
|
||||
|
||||
### Notable enhancements
|
||||
|
||||
- Added `React.Children.toArray` which takes a nested children object and returns a flat array with keys assigned to each child. This helper makes it easier to manipulate collections of children in your `render` methods, especially if you want to reorder or slice `this.props.children` before passing it down. In addition, `React.Children.map` now returns plain arrays too.
|
||||
- React uses `console.error` instead of `console.warn` for warnings so that browsers show a full stack trace in the console. (Our warnings appear when you use patterns that will break in future releases and for code that is likely to behave unexpectedly, so we do consider our warnings to be “must-fix” errors.)
|
||||
- Previously, including untrusted objects as React children [could result in an XSS security vulnerability](http://danlec.com/blog/xss-via-a-spoofed-react-element). This problem should be avoided by properly validating input at the application layer and by never passing untrusted objects around your application code. As an additional layer of protection, [React now tags elements](https://github.com/facebook/react/pull/4832) with a specific [ES2015 (ES6) `Symbol`](http://www.2ality.com/2014/12/es6-symbols.html) in browsers that support it, in order to ensure that React never considers untrusted JSON to be a valid element. If this extra security protection is important to you, you should add a `Symbol` polyfill for older browsers, such as the one included by [Babel’s polyfill](http://babeljs.io/docs/usage/polyfill/).
|
||||
- When possible, React DOM now generates XHTML-compatible markup.
|
||||
- React DOM now supports these standard HTML attributes: `capture`, `challenge`, `inputMode`, `is`, `keyParams`, `keyType`, `minLength`, `summary`, `wrap`. It also now supports these non-standard attributes: `autoSave`, `results`, `security`.
|
||||
- React DOM now supports these SVG attributes, which render into namespaced attributes: `xlinkActuate`, `xlinkArcrole`, `xlinkHref`, `xlinkRole`, `xlinkShow`, `xlinkTitle`, `xlinkType`, `xmlBase`, `xmlLang`, `xmlSpace`.
|
||||
- The `image` SVG tag is now supported by React DOM.
|
||||
- In React DOM, arbitrary attributes are supported on custom elements (those with a hyphen in the tag name or an `is="..."` attribute).
|
||||
- React DOM now supports these media events on `audio` and `video` tags: `onAbort`, `onCanPlay`, `onCanPlayThrough`, `onDurationChange`, `onEmptied`, `onEncrypted`, `onEnded`, `onError`, `onLoadedData`, `onLoadedMetadata`, `onLoadStart`, `onPause`, `onPlay`, `onPlaying`, `onProgress`, `onRateChange`, `onSeeked`, `onSeeking`, `onStalled`, `onSuspend`, `onTimeUpdate`, `onVolumeChange`, `onWaiting`.
|
||||
- Many small performance improvements have been made.
|
||||
- Many warnings show more context than before.
|
||||
- Add-Ons: A [`shallowCompare`](https://github.com/facebook/react/pull/3355) add-on has been added as a migration path for `PureRenderMixin` in ES6 classes.
|
||||
- Add-Ons: `CSSTransitionGroup` can now use [custom class names](https://github.com/facebook/react/blob/48942b85/docs/docs/10.1-animation.md#custom-classes) instead of appending `-enter-active` or similar to the transition name.
|
||||
|
||||
### New helpful warnings
|
||||
|
||||
- React DOM now warns you when nesting HTML elements invalidly, which helps you avoid surprising errors during updates.
|
||||
- Passing `document.body` directly as the container to `ReactDOM.render` now gives a warning as doing so can cause problems with browser extensions that modify the DOM.
|
||||
- Using multiple instances of React together is not supported, so we now warn when we detect this case to help you avoid running into the resulting problems.
|
||||
|
||||
### Notable bug fixes
|
||||
|
||||
- Click events are handled by React DOM more reliably in mobile browsers, particularly in Mobile Safari.
|
||||
- SVG elements are created with the correct namespace in more cases.
|
||||
- React DOM now renders `<option>` elements with multiple text children properly and renders `<select>` elements on the server with the correct option selected.
|
||||
- When two separate copies of React add nodes to the same document (including when a browser extension uses React), React DOM tries harder not to throw exceptions during event handling.
|
||||
- Using non-lowercase HTML tag names in React DOM (e.g., `React.createElement('DIV')`) no longer causes problems, though we continue to recommend lowercase for consistency with the JSX tag name convention (lowercase names refer to built-in components, capitalized names refer to custom components).
|
||||
- React DOM understands that these CSS properties are unitless and does not append “px” to their values: `animationIterationCount`, `boxOrdinalGroup`, `flexOrder`, `tabSize`, `stopOpacity`.
|
||||
- Add-Ons: When using the test utils, `Simulate.mouseEnter` and `Simulate.mouseLeave` now work.
|
||||
- Add-Ons: ReactTransitionGroup now correctly handles multiple nodes being removed simultaneously.
|
||||
|
||||
|
||||
### React Tools / Babel
|
||||
|
||||
#### Breaking Changes
|
||||
|
||||
- The `react-tools` package and `JSXTransformer.js` browser file [have been deprecated](/react/blog/2015/06/12/deprecating-jstransform-and-react-tools.html). You can continue using version `0.13.3` of both, but we no longer support them and recommend migrating to [Babel](http://babeljs.io/), which has built-in support for React and JSX.
|
||||
|
||||
#### New Features
|
||||
|
||||
- Babel 5.8.24 introduces **Inlining React elements:** The `optimisation.react.inlineElements` transform converts JSX elements to object literals like `{type: 'div', props: ...}` instead of calls to `React.createElement`. This should only be enabled in production, since it disables some development warnings/checks.
|
||||
- Babel 5.8.24 introduces **Constant hoisting for React elements:** The `optimisation.react.constantElements` transform hoists element creation to the top level for subtrees that are fully static, which reduces calls to `React.createElement` and the resulting allocations. More importantly, it tells React that the subtree hasn’t changed so React can completely skip it when reconciling. This should only be enabled in production, since it disables some development warnings/checks.
|
||||
|
||||
|
||||
## 0.13.3 (May 8, 2015)
|
||||
|
||||
### React Core
|
||||
|
||||
12
README.md
12
README.md
@@ -1,4 +1,4 @@
|
||||
# [React](https://facebook.github.io/react/) [](https://travis-ci.org/facebook/react) [](http://badge.fury.io/js/react)
|
||||
# [React](https://facebook.github.io/react/) [](https://travis-ci.org/facebook/react) [](http://badge.fury.io/js/react)
|
||||
|
||||
React is a JavaScript library for building user interfaces.
|
||||
|
||||
@@ -21,7 +21,7 @@ var HelloMessage = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
React.render(
|
||||
ReactDOM.render(
|
||||
<HelloMessage name="John" />,
|
||||
document.getElementById('container')
|
||||
);
|
||||
@@ -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.13.3.js"></script>
|
||||
<!-- In-browser JSX transformer, remove when pre-compiling JSX. -->
|
||||
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
|
||||
<script src="https://fb.me/react-0.14.8.js"></script>
|
||||
<!-- The ReactDOM Library -->
|
||||
<script src="https://fb.me/react-dom-0.14.8.js"></script>
|
||||
```
|
||||
|
||||
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-0.13.3.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-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.
|
||||
|
||||
If you'd like to use [bower](http://bower.io), it's as easy as:
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ require('yaml')
|
||||
desc "generate js from jsx"
|
||||
task :js do
|
||||
system "cp ../node_modules/babel/node_modules/babel-core/browser.min.js ./js/babel-browser.min.js"
|
||||
system "../node_modules/.bin/babel _js --out-dir=js"
|
||||
system "../node_modules/babel/bin/babel.js _js --out-dir=js"
|
||||
end
|
||||
|
||||
desc "watch js"
|
||||
@@ -24,6 +24,25 @@ task :update_version do
|
||||
end
|
||||
end
|
||||
|
||||
desc "update SRI hashes"
|
||||
task :update_hashes do
|
||||
map = {
|
||||
'react.js' => 'dev',
|
||||
'react.min.js' => 'prod',
|
||||
'react-with-addons.js' => 'addons_dev',
|
||||
'react-with-addons.min.js' => 'addons_prod',
|
||||
'react-dom.js' => 'dom_dev',
|
||||
'react-dom.min.js' => 'dom_prod',
|
||||
'react-dom-server.js' => 'dom_server_dev',
|
||||
'react-dom-server.min.js' => 'dom_server_prod'
|
||||
}
|
||||
site_config = YAML.load_file('_config.yml')
|
||||
map.each do |file, key|
|
||||
site_config['react_hashes'][key] = `openssl dgst -sha384 -binary ../../react-bower/#{file} | openssl base64 -A`
|
||||
end
|
||||
File.open('_config.yml', 'w+') { |f| f.write(site_config.to_yaml) }
|
||||
end
|
||||
|
||||
desc "update acknowledgements list"
|
||||
task :update_acknowledgements do
|
||||
authors = File.readlines('../AUTHORS').map {|author| author.gsub(/ <.*\n/,'')}
|
||||
|
||||
@@ -36,4 +36,13 @@ sass:
|
||||
sass_dir: _css
|
||||
gems:
|
||||
- jekyll-redirect-from
|
||||
react_version: 0.14.0-alpha
|
||||
react_version: 0.14.8
|
||||
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
|
||||
|
||||
@@ -1,44 +1,75 @@
|
||||
---
|
||||
- - Aaron Franks
|
||||
- - '839'
|
||||
- Aaron Franks
|
||||
- Aaron Gelter
|
||||
- Adam Krebs
|
||||
- Adam Mark
|
||||
- Adam Solove
|
||||
- Adam Timberlake
|
||||
- Adam Zapletal
|
||||
- Ahmad Wali Sidiqi
|
||||
- Alan Souza
|
||||
- Alan deLevie
|
||||
- Alastair Hole
|
||||
- Alex
|
||||
- Alex Boyd
|
||||
- Alex Lopatin
|
||||
- Alex Mykyta
|
||||
- Alex Pien
|
||||
- Alex Smith
|
||||
- Alex Zelenskiy
|
||||
- Alexander Shtuchkin
|
||||
- Alexander Solovyov
|
||||
- Alexander Tseung
|
||||
- Alexandre Gaudencio
|
||||
- Alexey Raspopov
|
||||
- Alexey Shamrin
|
||||
- Andre Z Sanchez
|
||||
- Andreas Savvides
|
||||
- Andreas Svensson
|
||||
- Andres Kalle
|
||||
- Andres Suarez
|
||||
- Andrew Cobby
|
||||
- Andrew Davey
|
||||
- Andrew Rasmussen
|
||||
- Andrew Sokolov
|
||||
- Andrew Zich
|
||||
- Andrey Popp
|
||||
- Anthony van der Hoorn
|
||||
- Antonio Ruberto
|
||||
- Antti Ahti
|
||||
- Anuj Tomar
|
||||
- AoDev
|
||||
- Areeb Malik
|
||||
- Aria Buckles
|
||||
- Aria Stewart
|
||||
- Arian Faurtosh
|
||||
- Artem Nezvigin
|
||||
- Austin Wright
|
||||
- Ayman Osman
|
||||
- Baraa Hamodi
|
||||
- Bartosz Kaszubowski
|
||||
- Basarat Ali Syed
|
||||
- Battaile Fauber
|
||||
- Beau Smith
|
||||
- Ben Alpert
|
||||
- Ben Anderson
|
||||
- Ben Foxall
|
||||
- Ben Jaffe
|
||||
- Ben Moss
|
||||
- Ben Newman
|
||||
- Ben Ripkens
|
||||
- Benjamin Keen
|
||||
- Benjamin Leiken
|
||||
- Benjamin Woodruff
|
||||
- Bill Fisher
|
||||
- Blaine Hatab
|
||||
- Blaine Kasten
|
||||
- Bob Eagan
|
||||
- Bob Ralian
|
||||
- Bob Renwick
|
||||
- Bojan Mihelac
|
||||
- Bradley Spaulding
|
||||
- Brandon Bloom
|
||||
- Brandon Tilley
|
||||
- Brian Cooke
|
||||
@@ -51,103 +82,166 @@
|
||||
- Bruno Škvorc
|
||||
- Cam Song
|
||||
- Cam Spiers
|
||||
- Carter Chung
|
||||
- Cassus Adam Banko
|
||||
- Cat Chen
|
||||
- Cedric Sohrauer
|
||||
- Charles Marsh
|
||||
- Chase Adams
|
||||
- Cheng Lou
|
||||
- Chitharanjan Das
|
||||
- Chris Grovers
|
||||
- Chris Ha
|
||||
- Chris Rebert
|
||||
- Chris Sciolla
|
||||
- Christian
|
||||
- Christian Alfoni
|
||||
- Christian Oliff
|
||||
- Christian Roman
|
||||
- Christoph Pojer
|
||||
- Christopher Monsanto
|
||||
- Clay Allsopp
|
||||
- Connor McSheffrey
|
||||
- Cory House
|
||||
- Cotton Hou
|
||||
- Cristovao Verstraeten
|
||||
- Damien Pellier
|
||||
- Dan Abramov
|
||||
- Dan Fox
|
||||
- Dan Schafer
|
||||
- Daniel Carlsson
|
||||
- Daniel Cousens
|
||||
- Daniel Friesen
|
||||
- Daniel Gasienica
|
||||
- Daniel Hejl
|
||||
- Daniel Lo Nigro
|
||||
- Daniel Mané
|
||||
- Daniel Miladinov
|
||||
- Daniel Rodgers-Pryor
|
||||
- Daniel Schonfeld
|
||||
- Danny Ben-David
|
||||
- Darcy
|
||||
- Daryl Lau
|
||||
- Darío Javier Cravero
|
||||
- David Baker
|
||||
- David Goldberg
|
||||
- David Greenspan
|
||||
- David Hellsing
|
||||
- David Hu
|
||||
- David Mininger
|
||||
- David Neubauer
|
||||
- David Percy
|
||||
- Denis Sokolov
|
||||
- Dennis Johnson
|
||||
- Devon Blandin
|
||||
- Devon Harvey
|
||||
- Dmitrii Abramov
|
||||
- Dmitry Blues
|
||||
- Dmitry Mazuro
|
||||
- Domenico Matteo
|
||||
- Don Abrams
|
||||
- Dustan Kasten
|
||||
- Dustin Getz
|
||||
- Dylan Harrington
|
||||
- Eduardo Garcia
|
||||
- Edvin Erikson
|
||||
- Elaine Fang
|
||||
- Enguerran
|
||||
- Eric Clemmons
|
||||
- Eric Eastwood
|
||||
- Eric Florenzano
|
||||
- Eric O'Connell
|
||||
- Eric Schoffstall
|
||||
- Erik Harper
|
||||
- Espen Hovlandsdal
|
||||
- Evan Coonrod
|
||||
- Fabio M. Costa
|
||||
- Federico Rampazzo
|
||||
- Felipe Oliveira Carvalho
|
||||
- Felix Gnass
|
||||
- Felix Kling
|
||||
- Fernando Correia
|
||||
- Frankie Bagnardi
|
||||
- François-Xavier Bois
|
||||
- Fred Zhao
|
||||
- G Scott Olson
|
||||
- G. Kay Lee
|
||||
- Gabe Levi
|
||||
- Gareth Nicholson
|
||||
- Garren Smith
|
||||
- Geert Pasteels
|
||||
- Geert-Jan Brits
|
||||
- George A Sisco III
|
||||
- Georgii Dolzhykov
|
||||
- Gilbert
|
||||
- Glen Mailer
|
||||
- Grant Timmerman
|
||||
- Greg Hurrell
|
||||
- Greg Perkins
|
||||
- Greg Roodt
|
||||
- Gregory
|
||||
- Guangqiang Dong
|
||||
- Guido Bouman
|
||||
- Harry Hull
|
||||
- Harry Marr
|
||||
- - Harry Moreno
|
||||
- Harshad Sabne
|
||||
- Hekar Khani
|
||||
- Hendrik Swanepoel
|
||||
- Henrik Nyh
|
||||
- Henry Zhu
|
||||
- Hou Chia
|
||||
- Hugo Jobling
|
||||
- Héliton Nordt
|
||||
- Ian Obermiller
|
||||
- Ignacio Carbajo
|
||||
- Igor Scekic
|
||||
- Ilya Shuklin
|
||||
- Ilyá Belsky
|
||||
- Ingvar Stepanyan
|
||||
- Irae Carvalho
|
||||
- Isaac Salier-Hellendag
|
||||
- Ivan Kozik
|
||||
- Ivan Krechetov
|
||||
- Ivan Vergiliev
|
||||
- J. Andrew Brassington
|
||||
- J. Renée Beach
|
||||
- JD Isaacks
|
||||
- JW
|
||||
- Jack Zhang
|
||||
- Jacob Gable
|
||||
- Jacob Greenleaf
|
||||
- Jae Hun Ro
|
||||
- Jaime Mingo
|
||||
- Jakub Malinowski
|
||||
- James
|
||||
- James Brantly
|
||||
- James Burnett
|
||||
- James Ide
|
||||
- James Long
|
||||
- James Pearce
|
||||
- James Seppi
|
||||
- James South
|
||||
- Jamie Wong
|
||||
- Jamis Charles
|
||||
- Jamison Dance
|
||||
- Jan Hancic
|
||||
- Jan Kassens
|
||||
- Jan Raasch
|
||||
- Jared Forsyth
|
||||
- Jason
|
||||
- Jason Bonta
|
||||
- Jason Ly
|
||||
- Jason Miller
|
||||
- Jason Quense
|
||||
- Jason Trill
|
||||
- Jason Webster
|
||||
- Jay Jaeho Lee
|
||||
- Jean Lauliac
|
||||
- Jed Watson
|
||||
- Jeff Barczewski
|
||||
- Jeff Carpenter
|
||||
- Jeff Chan
|
||||
- Jeff Hicken
|
||||
- Jeff Kolesky
|
||||
- Jeff Morrison
|
||||
- Jeff Welch
|
||||
@@ -158,50 +252,81 @@
|
||||
- Jim Sproch
|
||||
- Jimmy Jea
|
||||
- Jing Chen
|
||||
- Jinwoo Oh
|
||||
- Jiyeon Seo
|
||||
- Joe Stein
|
||||
- Joel Auterson
|
||||
- Johannes Baiter
|
||||
- Johannes Emerich
|
||||
- Johannes Lumpe
|
||||
- John Heroy
|
||||
- John Watson
|
||||
- Jon Beebe
|
||||
- Jon Chester
|
||||
- Jon Hester
|
||||
- Jon Madison
|
||||
- Jon Scott Clark
|
||||
- Jon Tewksbury
|
||||
- Jonas Enlund
|
||||
- Jonas Gebhardt
|
||||
- Jonathan Hsu
|
||||
- Jordan Harband
|
||||
- Jordan Walke
|
||||
- Jorrit Schippers
|
||||
- Joseph Nudell
|
||||
- Joseph Savona
|
||||
- Josh Bassett
|
||||
- Josh Duck
|
||||
- Josh Yudaken
|
||||
- Joshua Go
|
||||
- Joshua Goldberg
|
||||
- Joshua Ma
|
||||
- João Valente
|
||||
- Juan Serrano
|
||||
- Julen Ruiz Aizpuru
|
||||
- Julian Viereck
|
||||
- Julien Bordellier
|
||||
- Jun Wu
|
||||
- Juraj Dudak
|
||||
- Justin Jaffray
|
||||
- Justin Robison
|
||||
- Justin Woo
|
||||
- Kamron Batman
|
||||
- Karl Mikkelsen
|
||||
- Karpich Dmitry
|
||||
- Keito Uchiyama
|
||||
- Kevin Coughlin
|
||||
- Kevin Huang
|
||||
- Kevin Old
|
||||
- KimCoding
|
||||
- Kirk Steven Hansen
|
||||
- Kit Randel
|
||||
- Kohei TAKATA
|
||||
- Koo Youngmin
|
||||
- Kunal Mehta
|
||||
- Kurt Ruppel
|
||||
- Kyle Kelley
|
||||
- Kyle Mathews
|
||||
- Laurence Rowe
|
||||
- Laurent Etiemble
|
||||
- Lee Byron
|
||||
- Lee Jaeyoung
|
||||
- Lei
|
||||
- Leon Fedotov
|
||||
- Leon Yip
|
||||
- Leonardo YongUk Kim
|
||||
- Levi Buzolic
|
||||
- Levi McCallum
|
||||
- Lily
|
||||
- Logan Allen
|
||||
- Luigy Leon
|
||||
- Luke Horvat
|
||||
- MIKAMI Yoshiyuki
|
||||
- Marcin K.
|
||||
- Marcin Kwiatkowski
|
||||
- Marcin Szczepanski
|
||||
- Mariano Desanze
|
||||
- Marjan
|
||||
- Mark Anderson
|
||||
- Mark Funk
|
||||
- Mark Hintz
|
||||
@@ -212,28 +337,49 @@
|
||||
- Martin Andert
|
||||
- Martin Jul
|
||||
- Martin Konicek
|
||||
- Martin Mihaylov
|
||||
- Masaki KOBAYASHI
|
||||
- Mathieu M-Gosselin
|
||||
- Matias Singers
|
||||
- Matsunoki
|
||||
- Matt Brookes
|
||||
- Matt Dunn-Rankin
|
||||
- Matt Harrison
|
||||
- Matt Huggins
|
||||
- Matt Zabriskie
|
||||
- Matthew Dapena-Tretter
|
||||
- Matthew Johnston
|
||||
- Matthew King
|
||||
- Matthew Miner
|
||||
- Matthias Le Brun
|
||||
- Matti Nelimarkka
|
||||
- Max F. Albrecht
|
||||
- Max Heiber
|
||||
- Maxi Ferreira
|
||||
- Maxim Abramchuk
|
||||
- Merrick Christensen
|
||||
- Mert Kahyaoğlu
|
||||
- Michael Chan
|
||||
- Michael Randers-Pehrson
|
||||
- Michael Ridgway
|
||||
- Michael Warner
|
||||
- Michal Srb
|
||||
- Michelle Todd
|
||||
- Mihai Parparita
|
||||
- Mike D Pilsbury
|
||||
- - Mike Groseclose
|
||||
- Mikolaj Dadela
|
||||
- Minwe LUO
|
||||
- Miorel Palii
|
||||
- - Mouad Debbar
|
||||
- Morhaus
|
||||
- Mouad Debbar
|
||||
- Murad
|
||||
- Murray M. Moss
|
||||
- Nadeesha Cabral
|
||||
- Naman Goel
|
||||
- Nate Hunzaker
|
||||
- Nathan White
|
||||
- Neri Marschik
|
||||
- Nicholas Bergson-Shilcock
|
||||
- Nick Fitzgerald
|
||||
- Nick Gavalas
|
||||
@@ -242,14 +388,20 @@
|
||||
- Nick Thompson
|
||||
- Nick Williams
|
||||
- Niklas Boström
|
||||
- Ning Xia
|
||||
- Niole Nelson
|
||||
- Oiva Eskola
|
||||
- Oleg
|
||||
- Oleksii Markhovskyi
|
||||
- Oliver Zeigermann
|
||||
- Olivier Tassinari
|
||||
- Owen Coutts
|
||||
- Pablo Lacerda de Miranda
|
||||
- Paolo Moretti
|
||||
- Pascal Hartig
|
||||
- Patrick Laughlin
|
||||
- Patrick Stapleton
|
||||
- Paul Harper
|
||||
- Paul O’Shannessy
|
||||
- Paul Seiffert
|
||||
- Paul Shen
|
||||
@@ -262,6 +414,7 @@
|
||||
- Petri Lievonen
|
||||
- Pieter Vanderwerff
|
||||
- Pouja Nikray
|
||||
- Prathamesh Sonpatki
|
||||
- Preston Parry
|
||||
- Rafael
|
||||
- Rafal Dittwald
|
||||
@@ -269,76 +422,131 @@
|
||||
- Randall Randall
|
||||
- Ray
|
||||
- Raymond Ha
|
||||
- Reed Loden
|
||||
- Richard D. Worth
|
||||
- Richard Feldman
|
||||
- Richard Kho
|
||||
- Richard Littauer
|
||||
- Richard Livesey
|
||||
- Richard Wood
|
||||
- Rick Beerendonk
|
||||
- Riley Tomasek
|
||||
- Rob Arnold
|
||||
- Robert Knight
|
||||
- Robert Sedovsek
|
||||
- Robin Berjon
|
||||
- Roman Vanesyan
|
||||
- Russ
|
||||
- Ryan Seddon
|
||||
- Sahat Yalkabov
|
||||
- Saif Hakim
|
||||
- Sam Saccone
|
||||
- Sam Selikoff
|
||||
- Samy Al Zahrani
|
||||
- Sander Spies
|
||||
- Scott Burch
|
||||
- Scott Feeney
|
||||
- Sean Kinsey
|
||||
- Sebastian Markbåge
|
||||
- Seoh Char
|
||||
- Serg
|
||||
- Sergey Generalov
|
||||
- Sergey Rubanov
|
||||
- Seyi Adebajo
|
||||
- Shane O'Sullivan
|
||||
- Shaun Trennery
|
||||
- Sheraz
|
||||
- ShihChi Huang
|
||||
- Shim Won
|
||||
- Shota Kubota
|
||||
- Shripad K
|
||||
- Sibi
|
||||
- Simon Højberg
|
||||
- Simon Welsh
|
||||
- Sophia Westwood
|
||||
- Spencer Handley
|
||||
- Stefan Dombrowski
|
||||
- Stephen Murphy
|
||||
- Sterling Cobb
|
||||
- Steve Baker
|
||||
- Steven Luscher
|
||||
- Stoyan Stefanov
|
||||
- Sundeep Malladi
|
||||
- Sunny Juneja
|
||||
- Sven Helmberger
|
||||
- Sverre Johansen
|
||||
- Sébastien Lorber
|
||||
- Sławomir Laskowski
|
||||
- Taeho Kim
|
||||
- Tay Yang Shun
|
||||
- Ted Kim
|
||||
- Teodor Szente
|
||||
- Thomas Aylott
|
||||
- Thomas Boyt
|
||||
- Thomas Reggi
|
||||
- Thomas Röggla
|
||||
- Thomas Shaddox
|
||||
- Thomas Shafer
|
||||
- ThomasCrvsr
|
||||
- Tienchai Wirojsaksaree
|
||||
- Tim Routowicz
|
||||
- Tim Schaub
|
||||
- Timothy Yung
|
||||
- Tobias Reiss
|
||||
- Tom Haggie
|
||||
- Tom Hauburger
|
||||
- Tom MacWright
|
||||
- Tom Occhino
|
||||
- Tomasz Kołodziejski
|
||||
- Tony Spiro
|
||||
- Toru Kobayashi
|
||||
- Trinh Hoang Nhu
|
||||
- Tsung Hung
|
||||
- Tyler Brock
|
||||
- Ustin Zarubin
|
||||
- Vadim Chernysh
|
||||
- Varun Rau
|
||||
- Vasiliy Loginevskiy
|
||||
- Victor Alvarez
|
||||
- Victor Koenders
|
||||
- Ville Immonen
|
||||
- Vincent Riemer
|
||||
- Vincent Siao
|
||||
- Vipul A M
|
||||
- Vitaly Kramskikh
|
||||
- Vjeux
|
||||
- Volkan Unsal
|
||||
- Wayne Larsen
|
||||
- WickyNilliams
|
||||
- Wincent Colaiuta
|
||||
- Wout Mertens
|
||||
- Xavier Morel
|
||||
- XuefengWu
|
||||
- Yakov Dalinchuk
|
||||
- Yasar icli
|
||||
- YouBao Nong
|
||||
- Yuichi Hagio
|
||||
- Yuriy Dybskiy
|
||||
- Yuval Dekel
|
||||
- Zach Bruggeman
|
||||
- Zacharias
|
||||
- arush
|
||||
- brafdlog
|
||||
- chen
|
||||
- clariroid
|
||||
- claudiopro
|
||||
- cutbko
|
||||
- davidxi
|
||||
- dongmeng.ldm
|
||||
- iamchenxin
|
||||
- iamdoron
|
||||
- imagentleman
|
||||
- "Árni Hermann Reynisson"
|
||||
- "张敏"
|
||||
- laiso
|
||||
- li.li
|
||||
- sugarshin
|
||||
- wali-s
|
||||
- yiminghe
|
||||
- youmoo
|
||||
- zhangjg
|
||||
- Árni Hermann Reynisson
|
||||
- 凌恒
|
||||
- 张敏
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Map of short name to more information. `name` will be used but if you don't
|
||||
# want to use your real name, just use whatever. If url is included, your name
|
||||
# will be a link to the provided url.
|
||||
billandjing:
|
||||
name: Bill Fisher and Jing Chen
|
||||
benigeri:
|
||||
name: Paul Benigeri
|
||||
url: https://github.com/benigeri
|
||||
chenglou:
|
||||
name: Cheng Lou
|
||||
url: https://twitter.com/_chenglou
|
||||
@@ -12,14 +13,21 @@ Daniel15:
|
||||
fisherwebdev:
|
||||
name: Bill Fisher
|
||||
url: https://twitter.com/fisherwebdev
|
||||
gaearon:
|
||||
name: Dan Abramov
|
||||
url: https://twitter.com/dan_abramov
|
||||
jaredly:
|
||||
name: Jared Forsyth
|
||||
url: https://twitter.com/jaredforsyth
|
||||
jgebhardt:
|
||||
name: Jonas Gebhardt
|
||||
url: https://twitter.com/jonasgebhardt
|
||||
jimandsebastian:
|
||||
name: Jim Sproch and Sebastian Markbåge
|
||||
jimfb:
|
||||
name: Jim Sproch
|
||||
url: http://www.jimsproch.com
|
||||
jingc:
|
||||
name: Jing Chen
|
||||
url: https://twitter.com/jingc
|
||||
josephsavona:
|
||||
name: Joseph Savona
|
||||
url: https://twitter.com/en_JS
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
title: Videos
|
||||
- id: complementary-tools
|
||||
title: Complementary Tools
|
||||
href: https://github.com/facebook/react/wiki/Complementary-Tools
|
||||
- id: examples
|
||||
title: Examples
|
||||
href: https://github.com/facebook/react/wiki/Examples
|
||||
- title: Guides
|
||||
items:
|
||||
- id: why-react
|
||||
@@ -65,8 +67,12 @@
|
||||
title: PureRenderMixin
|
||||
- id: perf
|
||||
title: Performance Tools
|
||||
- id: shallow-compare
|
||||
title: Shallow Compare
|
||||
- id: advanced-performance
|
||||
title: Advanced Performance
|
||||
- id: context
|
||||
title: Context
|
||||
- title: Reference
|
||||
items:
|
||||
- id: top-level-api
|
||||
@@ -85,6 +91,8 @@
|
||||
title: Special Non-DOM Attributes
|
||||
- id: reconciliation
|
||||
title: Reconciliation
|
||||
- id: webcomponents
|
||||
title: Web Components
|
||||
- id: glossary
|
||||
title: React (Virtual) DOM Terminology
|
||||
- title: Flux
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
<p class="meta">
|
||||
{{ page.date | date: "%B %e, %Y" }}
|
||||
by
|
||||
{% if page.author.url %}
|
||||
<a href="{{page.author.url}}">{{ page.author.name }}</a>
|
||||
{% else %}
|
||||
{{ page.author.name }}
|
||||
{% endif %}
|
||||
{% for author in page.authors %}
|
||||
{% if author.url %}
|
||||
<a href="{{author.url}}">{{ author.name }}</a>
|
||||
{% else %}
|
||||
{{ author.name }}
|
||||
{% endif %}
|
||||
{% if forloop.last == false %} and {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
var TODO_COMPONENT = `
|
||||
var TodoList = React.createClass({
|
||||
render: function() {
|
||||
var createItem = function(itemText, index) {
|
||||
return <li key={index + itemText}>{itemText}</li>;
|
||||
var createItem = function(item) {
|
||||
return <li key={item.id}>{item.text}</li>;
|
||||
};
|
||||
return <ul>{this.props.items.map(createItem)}</ul>;
|
||||
}
|
||||
@@ -16,7 +16,7 @@ var TodoApp = React.createClass({
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var nextItems = this.state.items.concat([this.state.text]);
|
||||
var nextItems = this.state.items.concat([{text: this.state.text, id: Date.now()}]);
|
||||
var nextText = '';
|
||||
this.setState({items: nextItems, text: nextText});
|
||||
},
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<link rel="shortcut icon" href="/react/favicon.ico">
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ site.name }}" href="{{ site.url }}{{ site.baseurl }}/feed.xml">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css" />
|
||||
<link rel="stylesheet" href="/react/css/syntax.css">
|
||||
<link rel="stylesheet" href="/react/css/codemirror.css">
|
||||
<link rel="stylesheet" href="/react/css/react.css">
|
||||
@@ -28,6 +29,7 @@
|
||||
<script src="/react/js/es5-shim.min.js"></script>
|
||||
<script src="/react/js/es5-sham.min.js"></script>
|
||||
<![endif]-->
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script>
|
||||
<script src="/react/js/codemirror.js"></script>
|
||||
<script src="/react/js/javascript.js"></script>
|
||||
<script src="/react/js/react.js"></script>
|
||||
@@ -50,11 +52,14 @@
|
||||
<li><a href="/react/support.html"{% if page.id == 'support' %} class="active"{% endif %}>Support</a></li>
|
||||
<li><a href="/react/downloads.html"{% if page.id == 'downloads' %} class="active"{% endif %}>Download</a></li>
|
||||
<li><a href="/react/blog/"{% if page.sectionid == 'blog' %} class="active"{% endif %}>Blog</a></li>
|
||||
<li>
|
||||
<input id="algolia-doc-search" type="text" placeholder="Search docs..." />
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav-site nav-site-external">
|
||||
<li><a href="https://github.com/facebook/react">GitHub</a>
|
||||
<li><a href="https://facebook.github.io/react-native/">React Native</a>
|
||||
<li><a href="https://github.com/facebook/react">GitHub</a></li>
|
||||
<li><a href="https://facebook.github.io/react-native/">React Native</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -107,6 +112,12 @@
|
||||
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=623268441017527";
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}(document, 'script', 'facebook-jssdk'));
|
||||
|
||||
docsearch({
|
||||
apiKey: '36221914cce388c46d0420343e0bb32e',
|
||||
indexName: 'react',
|
||||
inputSelector: '#algolia-doc-search'
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -7,9 +7,9 @@ sectionid: docs
|
||||
{% include nav_docs.html %}
|
||||
|
||||
<div class="inner-content">
|
||||
<a class="edit-page-link" href="https://github.com/facebook/react/tree/master/docs/{{ page.path }}" target="_blank">Edit on GitHub</a>
|
||||
<h1>
|
||||
{{ page.title }}
|
||||
<a class="edit-page-link" href="https://github.com/facebook/react/tree/master/docs/{{ page.path }}" target="_blank">Edit on GitHub</a>
|
||||
</h1>
|
||||
<div class="subHeader">{{ page.description }}</div>
|
||||
|
||||
|
||||
8
docs/_layouts/redirect.html
Normal file
8
docs/_layouts/redirect.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Redirecting...</title>
|
||||
<link rel=canonical href="{{ page.dest_url }}">
|
||||
<meta http-equiv=refresh content="0; url={{ page.dest_url }}">
|
||||
<h1>Redirecting...</h1>
|
||||
<a href="{{ page.dest_url }}">Click here if you are not redirected.</a>
|
||||
<script>location="{{ page.dest_url }}"</script>
|
||||
@@ -7,7 +7,15 @@ module Authors
|
||||
class Generator < Jekyll::Generator
|
||||
def generate(site)
|
||||
site.posts.each do |post|
|
||||
post.data['author'] = site.data['authors'][post['author']]
|
||||
authors = []
|
||||
if post['author'].kind_of?(Array)
|
||||
for author in post['author']
|
||||
authors.push(site.data['authors'][author])
|
||||
end
|
||||
else
|
||||
authors.push(site.data['authors'][post['author']])
|
||||
end
|
||||
post.data['authors'] = authors
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,14 @@ module Jekyll
|
||||
pageID = @context.registers[:page]["id"]
|
||||
itemID = item["id"]
|
||||
href = item["href"] || "/react/docs/#{itemID}.html"
|
||||
className = pageID == itemID ? ' class="active"' : ''
|
||||
classes = []
|
||||
if pageID == itemID
|
||||
classes.push("active")
|
||||
end
|
||||
if item["href"]
|
||||
classes.push("external")
|
||||
end
|
||||
className = classes.size > 0 ? " class=\"#{classes.join(' ')}\"" : ""
|
||||
|
||||
return "<a href=\"#{href}\"#{className}>#{item["title"]}</a>"
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ While this is not going to work for all the attributes since they are camelCased
|
||||
|
||||
## Remarkable React
|
||||
|
||||
[Stoyan Stefanov](http://www.phpied.com/) gave a talk at [BrazilJS](http://braziljs.com.br/) about React and wrote an article with the content of the presentation. He goes through the difficulties of writting _active apps_ using the DOM API and shows how React handles it.
|
||||
[Stoyan Stefanov](http://www.phpied.com/) gave a talk at [BrazilJS](http://braziljs.com.br/) about React and wrote an article with the content of the presentation. He goes through the difficulties of writing _active apps_ using the DOM API and shows how React handles it.
|
||||
|
||||
> So how does exactly React deal with it internally? Two crazy ideas - virtual DOM and synthetic events.
|
||||
>
|
||||
|
||||
@@ -54,7 +54,7 @@ It's great to see the React community expand internationally. [This site](http:/
|
||||
|
||||
### Egghead.io video tutorials
|
||||
|
||||
Joe Maddalone ([@joemaddalone](https://twitter.com/joemaddalone)) of [egghead.io](https://egghead.io/) created a series of React video tutorials, such as [this](http://www.youtube-nocookie.com/watch?v=rFvZydtmsxM&feature=youtu.be&a) introduction to React Components. [[part 1](http://www.youtube-nocookie.com/watch?v=rFvZydtmsxM&feature=youtu.be&a)], [[part 2](http://www.youtube-nocookie.com/watch?v=5yvFLrt7N8M)]
|
||||
Joe Maddalone ([@joemaddalone](https://twitter.com/joemaddalone)) of [egghead.io](https://egghead.io/) created a series of React video tutorials, such as [this](http://www.youtube-nocookie.com/v/rFvZydtmsxM) introduction to React Components. [[part 1](http://www.youtube-nocookie.com/v/rFvZydtmsxM)], [[part 2](http://www.youtube-nocookie.com/v/5yvFLrt7N8M)]
|
||||
|
||||
### "React: Finally, a great server/client web stack"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Flux: An Application Architecture for React"
|
||||
author: fisherwebdevandjing
|
||||
author: [fisherwebdev, jingc]
|
||||
---
|
||||
|
||||
We recently spoke at one of f8's breakout session about Flux, a data flow architecture that works well with React. Check out the video here:
|
||||
|
||||
@@ -41,7 +41,7 @@ We have wanted to do this since before we even open sourced React. No more `/**
|
||||
|
||||
The React specific JSX transform no longer transforms to function calls. Instead we use `React.createElement` and pass it arguments. This allows us to make optimizations and better support React as a compile target for things like Om. Read more in the [React Elements introduction](/react/blog/2014/10/14/introducting-react-elements.html).
|
||||
|
||||
The result of this change is that we will no longer support arbitrary function calls. We understand that the ability to do was was a convenient shortcut for many people but we believe the gains will be worth it.
|
||||
The result of this change is that we will no longer support arbitrary function calls. We understand that the ability to do was a convenient shortcut for many people but we believe the gains will be worth it.
|
||||
|
||||
|
||||
### JSX Lower-case Convention
|
||||
|
||||
@@ -17,7 +17,7 @@ stick with the originally planned format and venue on Facebook's campus.
|
||||
|
||||
Unfortunately, this means that we can only accept a small number of the awesome
|
||||
conference talk proposals. In order to make sure attendees get a fair shot at
|
||||
registering, we're going to to sell tickets in three separate first-come,
|
||||
registering, we're going to sell tickets in three separate first-come,
|
||||
first-serve phases. **Tickets will cost $200 regardless of which phase they are
|
||||
purchased from and all proceeds will go to charity**.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ layout: post
|
||||
author: steveluscher
|
||||
---
|
||||
|
||||
It was a privilege to welcome the React community to Facebook HQ on January 28–29 for the first-ever React.js Conf, and a pleasure to be be able to unveil three new technologies that we've been using internally at Facebook for some time: GraphQL, Relay, and React Native.
|
||||
It was a privilege to welcome the React community to Facebook HQ on January 28–29 for the first-ever React.js Conf, and a pleasure to be able to unveil three new technologies that we've been using internally at Facebook for some time: GraphQL, Relay, and React Native.
|
||||
|
||||
## The talks
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "Building The Facebook News Feed With Relay"
|
||||
author: josephsavona
|
||||
---
|
||||
|
||||
At React.js Conf in January we gave a preview of Relay, a new framework for building data-driven applications in React. In this post, we'll describe the process of creating a Relay application. This post assumes some familiarity with the concepts of Relay and GraphQL, so if you haven't already we recommend reading [our introductory blog post](/react/blog/2015/02/20/introducing-relay-and-graphql.html) or watching [the conference talk](https://www.youtube-nocookie.com/watch?v=9sc8Pyc51uU).
|
||||
At React.js Conf in January we gave a preview of Relay, a new framework for building data-driven applications in React. In this post, we'll describe the process of creating a Relay application. This post assumes some familiarity with the concepts of Relay and GraphQL, so if you haven't already we recommend reading [our introductory blog post](/react/blog/2015/02/20/introducing-relay-and-graphql.html) or watching [the conference talk](https://www.youtube-nocookie.com/v/9sc8Pyc51uU).
|
||||
|
||||
We're working hard to prepare GraphQL and Relay for public release. In the meantime, we'll continue to provide information about what you can expect.
|
||||
|
||||
@@ -40,20 +40,18 @@ The first step is a React `<Story>` component that accepts a `story` prop with t
|
||||
|
||||
```javascript
|
||||
// Story.react.js
|
||||
class Story extends React.Component {
|
||||
export default class Story extends React.Component {
|
||||
render() {
|
||||
var story = this.props.story;
|
||||
return (
|
||||
<View>
|
||||
<Image uri={story.author.profile_picture.uri} />
|
||||
<Image uri={story.author.profilePicture.uri} />
|
||||
<Text>{story.author.name}</Text>
|
||||
<Text>{story.text}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Story;
|
||||
```
|
||||
|
||||
<br/>
|
||||
@@ -66,41 +64,41 @@ Relay automates the process of fetching data for components by wrapping existing
|
||||
// Story.react.js
|
||||
class Story extends React.Component { ... }
|
||||
|
||||
module.exports = Relay.createContainer(Story, {
|
||||
queries: {
|
||||
export default Relay.createContainer(Story, {
|
||||
fragments: {
|
||||
story: /* TODO */
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Before adding the GraphQL query, let's look at the component hierarchy this creates:
|
||||
Before adding the GraphQL fragment, let's look at the component hierarchy this creates:
|
||||
|
||||
<img src="/react/img/blog/relay-components/relay-containers.png" width="397" alt="React Container Data Flow" />
|
||||
|
||||
Most props will be passed through from the container to the original component. However, Relay will return the query results for a prop whenever a query is defined. In this case we'll add a GraphQL query for `story`:
|
||||
Most props will be passed through from the container to the original component. However, Relay will return the query results for a prop whenever a fragment is defined. In this case we'll add a GraphQL fragment for `story`:
|
||||
|
||||
```javascript
|
||||
// Story.react.js
|
||||
class Story extends React.Component { ... }
|
||||
|
||||
module.exports = Relay.createContainer(Story, {
|
||||
queries: {
|
||||
story: graphql`
|
||||
Story {
|
||||
export default Relay.createContainer(Story, {
|
||||
fragments: {
|
||||
story: () => Relay.QL`
|
||||
fragment on Story {
|
||||
author {
|
||||
name,
|
||||
profile_picture {
|
||||
name
|
||||
profilePicture {
|
||||
uri
|
||||
}
|
||||
},
|
||||
}
|
||||
text
|
||||
}
|
||||
`
|
||||
}
|
||||
`,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Queries use ES6 template literals tagged with the `graphql` function. Similar to how JSX transpiles to plain JavaScript objects and function calls, these template literals transpile to plain objects that describe queries. Note that the query's structure closely matches the object structure that we expected in `<Story>`'s render function.
|
||||
Queries use ES6 template literals tagged with the `Relay.QL` function. Similar to how JSX transpiles to plain JavaScript objects and function calls, these template literals transpile to plain objects that describe fragments. Note that the fragment's structure closely matches the object structure that we expected in `<Story>`'s render function.
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -112,7 +110,7 @@ We can render a Relay component by providing Relay with the component (`<Story>`
|
||||
{
|
||||
author: {
|
||||
name: "Greg",
|
||||
profile_picture: {
|
||||
profilePicture: {
|
||||
uri: "https://…"
|
||||
}
|
||||
},
|
||||
@@ -159,35 +157,35 @@ module.exports = NewsFeed;
|
||||
|
||||
`<NewsFeed>` has two new requirements: it composes `<Story>` and requests more data at runtime.
|
||||
|
||||
Just as React views can be nested, Relay queries can compose queries from child components. Composition in GraphQL uses ES6 template literal substitution: `${Component.getQuery('prop')}`. Pagination can be accomplished with a query parameter, specified with `<param>` (as in `stories(first: <count>)`):
|
||||
Just as React views can be nested, Relay components can compose query fragments from child components. Composition in GraphQL uses ES6 template literal substitution: `${Component.getFragment('prop')}`. Pagination can be accomplished with a variable, specified with `$variable` (as in `stories(first: $count)`):
|
||||
|
||||
```javascript
|
||||
// NewsFeed.react.js
|
||||
class NewsFeed extends React.Component { ... }
|
||||
|
||||
module.exports = Relay.createContainer(NewsFeed, {
|
||||
queryParams: {
|
||||
count: 3 /* default to 3 stories */
|
||||
export default Relay.createContainer(NewsFeed, {
|
||||
initialVariables: {
|
||||
count: 3 /* default to 3 stories */
|
||||
},
|
||||
queries: {
|
||||
viewer: graphql`
|
||||
Viewer {
|
||||
stories(first: <count>) { /* fetch viewer's stories */
|
||||
edges { /* traverse the graph */
|
||||
fragments: {
|
||||
viewer: () => Relay.QL`
|
||||
fragment on Viewer {
|
||||
stories(first: $count) { /* fetch viewer's stories */
|
||||
edges { /* traverse the graph */
|
||||
node {
|
||||
${Story.getQuery('story')} /* compose child query */
|
||||
${Story.getFragment('story')} /* compose child fragment */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
`,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Whenever `<NewsFeed>` is rendered, Relay will recursively expand all the composed queries and fetch them in a single trip to the server. In this case, the `text` and `author` data will be fetched for each of the 3 story nodes.
|
||||
Whenever `<NewsFeed>` is rendered, Relay will recursively expand all the composed fragments and fetch the queries in a single trip to the server. In this case, the `text` and `author` data will be fetched for each of the 3 story nodes.
|
||||
|
||||
Query parameters are available to components as `props.queryParams` and can be modified with `props.setQueryParams(nextParams)`. We can use these to implement pagination:
|
||||
Query variables are available to components as `props.relay.variables` and can be modified with `props.relay.setVariables(nextVariables)`. We can use these to implement pagination:
|
||||
|
||||
```javascript
|
||||
// NewsFeed.react.js
|
||||
@@ -196,16 +194,16 @@ class NewsFeed extends React.Component {
|
||||
|
||||
loadMore() {
|
||||
// read current params
|
||||
var count = this.props.queryParams.count;
|
||||
var count = this.props.relay.variables.count;
|
||||
// update params
|
||||
this.props.setQueryParams({
|
||||
count: count + 5
|
||||
this.props.relay.setVariables({
|
||||
count: count + 5,
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now when `loadMore()` is called, Relay will send a GraphQL request for the additional five stories. When these stories are fetched, the component will re-render with the new stories available in `props.viewer.stories` and the updated count reflected in `props.queryParams.count`.
|
||||
Now when `loadMore()` is called, Relay will send a GraphQL request for the additional five stories. When these stories are fetched, the component will re-render with the new stories available in `props.viewer.stories` and the updated count reflected in `props.relay.variables.count`.
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ We believe there are a number of weakness in typical REST systems, ones that are
|
||||
|
||||
* Fetching complicated object graphs require multiple round trips between the client and server to render single views. For mobile applications operating in variable network conditions, these multiple roundtrips are highly undesirable.
|
||||
* Invariably fields and additional data are added to REST endpoints as the system requirements change. However, old clients also receive this additional data as well, because the data fetching specification is encoded on the server rather than the client. As result, these payloads tend to grow over time for all clients. When this becomes a problem for a system, one solution is to overlay a versioning system onto the REST endpoints. Versioning also complicates a server, and results in code duplication, spaghetti code, or a sophisticated, hand-rolled infrastructure to manage it. Another solution to limit over-fetching is to provide multiple views – such as “compact” vs “full” – of the same REST endpoint, however this coarse granularity often does not offer adequate flexibility.
|
||||
* REST endpoints are usually weakly-typed and lack machine-readable metadata. While there is much debate about the merits of strong- versus weak-typing in distributed systems, we believe in strong typing because of the correctness guarantees and tooling opportunities it provides. Developer deal with systems that lack this metadata by inspecting frequently out-of-date documentation and then writing code against the documentation.
|
||||
* REST endpoints are usually weakly-typed and lack machine-readable metadata. While there is much debate about the merits of strong- versus weak-typing in distributed systems, we believe in strong typing because of the correctness guarantees and tooling opportunities it provides. Developers deal with systems that lack this metadata by inspecting frequently out-of-date documentation and then writing code against the documentation.
|
||||
* Many of these attributes are linked to the fact that “REST is intended for long-lived network-based applications that span multiple organizations” [according to its inventor](http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven). This is not a requirement for APIs that serve a client app built within the same organization.
|
||||
|
||||
Nearly all externally facing REST APIs we know of trend or end up in these non-ideal states, as well as nearly all *internal* REST APIs. The consequences of opaqueness and over-fetching are more severe in internal APIs since their velocity of change and level of usage is almost always higher.
|
||||
@@ -90,7 +90,7 @@ Because of multiple round-trips and over-fetching, applications built in the RES
|
||||
Many applications have no formalized client-server contract. Product developers access server capabilities through *ad hoc* endpoints and write custom code to fetch the data they need. Servers define procedures, and they return data. This approach has the virtue of simplicity, but can often become untenable as systems age.
|
||||
|
||||
* These systems typically define a custom endpoint per view. For systems with a wide surface area this can quickly grow into a maintenance nightmare of orphaned endpoints, inconsistent tooling, and massive server code duplication. Disciplined engineering organizations can mitigate these issues with great engineering practices, high quality abstractions, and custom tooling. However, given our experience we believe that custom endpoints tend to lead to entropic server codebases.
|
||||
* Much like REST, the payloads of custom endpoints grow monotonically (even with mitigation from versioning systems) as the server evolves. Deployed clients cannot break, and, with rapid release cycles and backwards compatibility guarantees, distributed applications will have large numbers of extant versions. Under these constraints it is difficult remove data from a custom endpoint.
|
||||
* Much like REST, the payloads of custom endpoints grow monotonically (even with mitigation from versioning systems) as the server evolves. Deployed clients cannot break, and, with rapid release cycles and backwards compatibility guarantees, distributed applications will have large numbers of extant versions. Under these constraints it is difficult to remove data from a custom endpoint.
|
||||
* Custom endpoints tend to – for a client developer – create a clunky, multi-language, multi-environment development process. No matter if the data has been accessed before in a different view, they are required to first change the custom endpoint, then deploy that code to a server accessible from a mobile device, and only then change the client to utilize that data. In GraphQL – unless the data in the view is completely new to the entire system – a product developer adds a field to a GraphQL query and the work on the client continues unabated.
|
||||
* Much like REST, most systems with custom endpoints do not have a formalized type system, which eliminates the possibility for the tools and guarantees that introspective type systems can provide. Some custom-endpoint-driven systems do use a strongly typed serialization scheme, such as Protocol Buffers, Thrift, or XML. Those do allow for direct parsing of responses into typed classes and eliminating boilerplate shuffling from JSON into handwritten classes. These systems are as not as expressive and flexible as GraphQL, and the other downsides of *ad hoc* endpoints remain.
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ These builds are also available in the `react` package on bower.
|
||||
ReactDOM.render(<MyComponent />, node);
|
||||
```
|
||||
|
||||
We’ve published the [automated codemod script](https://github.com/facebook/react/blob/master/packages/react-codemod/README.md) we used at Facebook to help you with this transition.
|
||||
We’ve published the [automated codemod script](https://github.com/reactjs/react-codemod/blob/master/README.md) we used at Facebook to help you with this transition.
|
||||
|
||||
The add-ons have moved to separate packages as well: `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`, and `react-addons-update`, plus `ReactDOM.unstable_batchedUpdates` in `react-dom`.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "ReactDOM.render and the Top Level React API"
|
||||
author: jimandsebastian
|
||||
author: ["jimfb", "sebmarkbage"]
|
||||
---
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ Like always, we have a few breaking changes in this release. We know changes can
|
||||
|
||||
If your code is free of warnings when running under React 0.13, upgrading should be easy. We have two new small breaking changes that didn't give a warning in 0.13 (see below). Every new change in 0.14, including the major changes below, is introduced with a runtime warning and will work as before until 0.15, so you don't have to worry about your app breaking with this upgrade.
|
||||
|
||||
For the two major changes which require significant code changes, we've included [codemod scripts](https://github.com/reactjs/react-codemod/blob/master/README.md) to help you upgrade your code automatically.
|
||||
|
||||
See the changelog below for more details.
|
||||
|
||||
## Installation
|
||||
@@ -64,7 +66,7 @@ If you can’t use `npm` yet, we provide pre-built browser builds for your conve
|
||||
ReactDOM.render(<MyComponent />, node);
|
||||
```
|
||||
|
||||
The old names will continue to work with a warning until 0.15 is released, and we’ve published the [automated codemod script](https://github.com/facebook/react/blob/master/packages/react-codemod/README.md) we used at Facebook to help you with this transition.
|
||||
The old names will continue to work with a warning until 0.15 is released, and we’ve published the [automated codemod script](https://github.com/reactjs/react-codemod/blob/master/README.md) we used at Facebook to help you with this transition.
|
||||
|
||||
The add-ons have moved to separate packages as well:
|
||||
- `react-addons-clone-with-props`
|
||||
@@ -99,7 +101,7 @@ If you can’t use `npm` yet, we provide pre-built browser builds for your conve
|
||||
```
|
||||
|
||||
This change also applies to the return result of `ReactDOM.render` when passing a DOM node as the top component. As with refs, this change does not affect custom components.
|
||||
|
||||
|
||||
With this change, we’re deprecating `.getDOMNode()` and replacing it with `ReactDOM.findDOMNode` (see below). If your components are currently using `.getDOMNode()`, they will continue to work with a warning until 0.15.
|
||||
|
||||
- #### Stateless functional components
|
||||
@@ -124,7 +126,7 @@ If you can’t use `npm` yet, we provide pre-built browser builds for your conve
|
||||
```
|
||||
|
||||
These components behave just like a React class with only a `render` method defined. Since no component instance is created for a functional component, any `ref` added to one will evaluate to `null`. Functional components do not have lifecycle methods, but you can set `.propTypes` and `.defaultProps` as properties on the function.
|
||||
|
||||
|
||||
This pattern is designed to encourage the creation of these simple components that should comprise large portions of your apps. In the future, we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations.
|
||||
|
||||
- #### Deprecation of react-tools
|
||||
@@ -133,7 +135,7 @@ If you can’t use `npm` yet, we provide pre-built browser builds for your conve
|
||||
|
||||
- #### Compiler optimizations
|
||||
|
||||
React now supports two compiler optimizations that can be enabled in Babel 5.8.23 and newer. Both of these transforms **should be enabled only in production** (e.g., just before minifying your code) because although they improve runtime performance, they make warning messages more cryptic and skip important checks that happen in development mode, including propTypes.
|
||||
React now supports two compiler optimizations that can be enabled in Babel 5.8.24 and newer. Both of these transforms **should be enabled only in production** (e.g., just before minifying your code) because although they improve runtime performance, they make warning messages more cryptic and skip important checks that happen in development mode, including propTypes.
|
||||
|
||||
**Inlining React elements:** The `optimisation.react.inlineElements` transform converts JSX elements to object literals like `{type: 'div', props: ...}` instead of calls to `React.createElement`.
|
||||
|
||||
@@ -159,7 +161,7 @@ Each of these changes will continue to work as before with a new warning until t
|
||||
|
||||
- Due to the DOM node refs change mentioned above, `this.getDOMNode()` is now deprecated and `ReactDOM.findDOMNode(this)` can be used instead. Note that in most cases, calling `findDOMNode` is now unnecessary – see the example above in the “DOM node refs” section.
|
||||
|
||||
With each returned DOM node, we've added a `getDOMNode` method for backwards compatibility that will work with a warning until 0.15. If you have a large codebase, you can use our [automated codemod script](https://github.com/facebook/react/blob/master/packages/react-codemod/README.md) to change your code automatically.
|
||||
With each returned DOM node, we've added a `getDOMNode` method for backwards compatibility that will work with a warning until 0.15. If you have a large codebase, you can use our [automated codemod script](https://github.com/reactjs/react-codemod/blob/master/README.md) to change your code automatically.
|
||||
|
||||
- `setProps` and `replaceProps` are now deprecated. Instead, call ReactDOM.render again at the top level with the new props.
|
||||
- ES6 component classes must now extend `React.Component` in order to enable stateless function components. The [ES3 module pattern](/react/blog/2015/01/27/react-v0.13.0-beta-1.html#other-languages) will continue to work.
|
||||
|
||||
86
docs/_posts/2015-10-19-reactiflux-is-moving-to-discord.md
Normal file
86
docs/_posts/2015-10-19-reactiflux-is-moving-to-discord.md
Normal file
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: "Reactiflux is moving to Discord"
|
||||
author: benigeri
|
||||
---
|
||||
|
||||
TL;DR: Slack decided that Reactiflux had too many members and disabled new invites. Reactiflux is moving to Discord. Join us: [http://join.reactiflux.com](http://join.reactiflux.com/)
|
||||
|
||||
## What happened with Slack?
|
||||
|
||||
A few weeks ago, Reactiflux reached 7,500 members on Slack. Shortly after, Slack decided we were too big and disabled invites. There was no way for new users to join. Many of us were sad and upset. We loved Slack. Our community was built around it.
|
||||
|
||||
We reached out to Slack several times, but their decision was firm. Our large community caused performance issues. Slack wants to focus on building a great product for teams, not necessarily large open communities. Losing focus and building for too many use cases always leads to product bloat, and eventually a decrease in quality.
|
||||
|
||||
## So… why Discord?
|
||||
|
||||
After a [long and thorough debate](https://github.com/reactiflux/volunteers/issues/25), Discord quickly emerged as the most promising service. After just a few days, 400 members had joined the Discord server, and many already loved it.
|
||||
|
||||
### Easiest to join
|
||||
|
||||
Discord is the easiest platform to join. New users can immediately join our conversations without having to create an account. All they need to do is provide a name. No permission granting, no password, no email confirmation.
|
||||
|
||||
This is critically useful for us, and will make Reactiflux even more open and accessible.
|
||||
|
||||
### Great apps
|
||||
|
||||
Out of all of the services we’ve tried, Discord’s apps are by far the most polished. They are well designed, easy to use, and surprisingly fast. In addition to the web app, they have mobile apps on both iOS and Android as well as desktop apps for OS X and Windows, with Linux support coming soon.
|
||||
|
||||
Their desktop apps are built with React and Electron, and their iOS app is built with React Native.
|
||||
|
||||
### Moderation tools
|
||||
|
||||
So far, we’ve been fortunate not to have to deal with spammers and trolls. As our community continues to grow, that might change. Unsurprisingly, Discord is the only app we’ve seen with legitimate moderation tools. It was built for gaming communities, after all.
|
||||
|
||||
### Great multiple Server support
|
||||
|
||||
Your Discord account works with every Discord server, which is the equivalent of a Slack team. You don’t need to create a new account every time you join a new team. You can join new servers in one click, and it’s very easy to switch between them. Discord messages also work across servers, so your personal conversations are not scoped to a single server.
|
||||
|
||||
Instead of having one huge, crowded Reactiflux server, we can branch off closely related channels into sub-servers. Communities will start overlapping, and it will be easy to interact with non-Reactiflux channels.
|
||||
|
||||
### It’s hosted
|
||||
|
||||
Self-hosted apps require maintenance. We’re all busy, and we can barely find the time to keep our landing page up to date and running smoothly. More than anything, we need a stable platform, and we don’t have the resources to guarantee that right now.
|
||||
|
||||
It’s a much safer bet to offload the hosting to Discord, who is already keeping the lights on for all their users.
|
||||
|
||||
### We like the team
|
||||
|
||||
And they seem to like us back. They are excited for us to join them, and they’ve been very responsive to our feedback and suggestions.
|
||||
|
||||
They implemented code syntax highlighting just a few days after we told them we needed it.
|
||||
|
||||
Discord’s team has already built a solid suite of apps, and they have shown us how much they care about their users. We’re excited to see how they will continue to improve their product.
|
||||
|
||||
## And what’s the catch?
|
||||
|
||||
Choosing the best chat service is subjective. There are a million reasons why Discord *might be* a terrible idea. Here are the ones that we’re most worried about:
|
||||
|
||||
### Difficult channel management
|
||||
|
||||
Channel management seems to be the biggest issue. There is no way to opt out of channels; you can only mute them. And you can only mute channels one by one. There is no way to star channels, and channels can only be sorted on the server level. Each user will see the list of channels in the same order.
|
||||
|
||||
As the number of channels grow, it will be challenging to keep things in order. Branching off sub-servers will help, and we will keep an easily accessible directory of channels across our main server and all of the sub-servers.
|
||||
|
||||
We can build simple tools to make channel lookup easier, and the Discord team is working on improvements that should make this more manageable.
|
||||
|
||||
### No Search
|
||||
|
||||
Lack of search is clearly a bummer, but Discord is working on it. Search is coming!
|
||||
|
||||
### Firewall
|
||||
|
||||
A couple of users aren’t able to access Discord at work since other corporate filters classify it as a gaming application. This sucks, but it seems to be a rare case. So far, it seems only to affect 0.6% of our current community (3/500).
|
||||
|
||||
We hope that these users can get Discord's domains whitelisted, and we’ll try to find a solution if this is a widespread issue. The Discord team is aware of the issue as well.
|
||||
|
||||
## Is Discord going to disappear tomorrow?
|
||||
|
||||
Probably not tomorrow. They have 14 people [full time](https://discordapp.com/company), and they’ve raised money from some of the best investors in Silicon Valley, including [Benchmark](http://www.benchmark.com/) and [Accel](http://www.accel.com/companies/).
|
||||
|
||||
By focusing on gaming communities, Discord has differentiated itself from the many other communication apps. Discord is well received and has a rapidly growing user base. They plan to keep their basic offerings free for unlimited users and hope to make money with premium offerings (themes, add-ons, content, and more).
|
||||
|
||||
## Join us!
|
||||
|
||||
More than 500 of us have already migrated to the new Reactiflux. Join us, we're one click away: [http://join.reactiflux.com](http://join.reactiflux.com/)
|
||||
|
||||
*Note: Jordan Hawker’s thorough [research](http://jhawk.co/team-chat-comparison) made our decision a lot easier.*
|
||||
40
docs/_posts/2015-10-28-react-v0.14.1.md
Normal file
40
docs/_posts/2015-10-28-react-v0.14.1.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "React v0.14.1"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
After a couple weeks of having more people use v0.14, we're ready to ship a patch release addressing a few issues. Thanks to everybody who has reported issues and written patches!
|
||||
|
||||
The release is now available for download:
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-0.14.1.js>
|
||||
Minified build for production: <https://fb.me/react-0.14.1.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-0.14.1.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-0.14.1.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-0.14.1.js>
|
||||
Minified build for production: <https://fb.me/react-dom-0.14.1.min.js>
|
||||
|
||||
We've also published version `0.14.1` of the `react`, `react-dom`, and addons packages on npm and the `react` package on bower.
|
||||
|
||||
- - -
|
||||
|
||||
## Changelog
|
||||
|
||||
### React DOM
|
||||
- Fixed bug where events wouldn't fire in old browsers when using React in development mode
|
||||
- Fixed bug preventing use of `dangerouslySetInnerHTML` with Closure Compiler Advanced mode
|
||||
- Added support for `srcLang`, `default`, and `kind` attributes for `<track>` elements
|
||||
- Added support for `color` attribute
|
||||
- Ensured legacy `.props` access on DOM nodes is updated on re-renders
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Fixed `scryRenderedDOMComponentsWithClass` so it works with SVG
|
||||
|
||||
### React CSSTransitionGroup Add-on
|
||||
- Fix bug preventing `0` to be used as a timeout value
|
||||
|
||||
### React on Bower
|
||||
- Added `react-dom.js` to `main` to improve compatibility with tooling
|
||||
31
docs/_posts/2015-11-02-react-v0.14.2.md
Normal file
31
docs/_posts/2015-11-02-react-v0.14.2.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
title: "React v0.14.2"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
We have a quick update following the release of 0.14.1 last week. It turns out we broke a couple things in the development build of React when using Internet Explorer. Luckily it was only the development build, so your production applications were unaffected. This release is mostly to address those issues. There is one notable change if consuming React from npm. For the `react-dom` package, we moved `react` from a regular dependency to a peer dependency. This will impact very few people as these two are typically installed together at the top level, but it will fix some issues with dependencies of installed components also using `react` as a peer dependency.
|
||||
|
||||
The release is now available for download:
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-0.14.2.js>
|
||||
Minified build for production: <https://fb.me/react-0.14.2.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-0.14.2.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-0.14.2.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-0.14.2.js>
|
||||
Minified build for production: <https://fb.me/react-dom-0.14.2.min.js>
|
||||
|
||||
We've also published version `0.14.2` of the `react`, `react-dom`, and addons packages on npm and the `react` package on bower.
|
||||
|
||||
- - -
|
||||
|
||||
## Changelog
|
||||
|
||||
### React DOM
|
||||
- Fixed bug with development build preventing events from firing in some versions of Internet Explorer & Edge
|
||||
- Fixed bug with development build when using es5-sham in older versions of Internet Explorer
|
||||
- Added support for `integrity` attribute
|
||||
- Fixed bug resulting in `children` prop being coerced to a string for custom elements, which was not the desired behavior.
|
||||
- Moved `react` from `dependencies` to `peerDependencies` to match expectations and align with `react-addons-*` packages
|
||||
40
docs/_posts/2015-11-18-react-v0.14.3.md
Normal file
40
docs/_posts/2015-11-18-react-v0.14.3.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "React v0.14.3"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
It's time for another installment of React patch releases! We didn't break anything in v0.14.2 but we do have a couple of other bugs we're fixing. The biggest change in this release is actually an addition of a new built file. We heard from a number of people that they still need the ability to use React to render to a string on the client. While the use cases are not common and there are other ways to achieve this, we decided that it's still valuable to support. So we're now building `react-dom-server.js`, which will be shipped to Bower and in the `dist/` directory of the `react-dom` package on npm. This file works the same way as `react-dom.js` and therefore requires that the primary React build has already been included on the page.
|
||||
|
||||
The release is now available for download:
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-0.14.3.js>
|
||||
Minified build for production: <https://fb.me/react-0.14.3.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-0.14.3.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-0.14.3.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-0.14.3.js>
|
||||
Minified build for production: <https://fb.me/react-dom-0.14.3.min.js>
|
||||
* **React DOM Server** (include React in the page before React DOM Server)
|
||||
Dev build with warnings: <https://fb.me/react-dom-server-0.14.3.js>
|
||||
Minified build for production: <https://fb.me/react-dom-server-0.14.3.min.js>
|
||||
|
||||
We've also published version `0.14.3` of the `react`, `react-dom`, and addons packages on npm and the `react` package on bower.
|
||||
|
||||
- - -
|
||||
|
||||
## Changelog
|
||||
|
||||
### React DOM
|
||||
- Added support for `nonce` attribute for `<script>` and `<style>` elements
|
||||
- Added support for `reversed` attribute for `<ol>` elements
|
||||
|
||||
### React TestUtils Add-on
|
||||
- Fixed bug with shallow rendering and function refs
|
||||
|
||||
### React CSSTransitionGroup Add-on
|
||||
- Fixed bug resulting in timeouts firing incorrectly when mounting and unmounting rapidly
|
||||
|
||||
### React on Bower
|
||||
- Added `react-dom-server.js` to expose `renderToString` and `renderToStaticMarkup` for usage in the browser
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: React.js Conf 2016 Diversity Scholarship
|
||||
author: zpao
|
||||
---
|
||||
|
||||
I am thrilled to announced that we will be organizing another diversity scholarship program for the upcoming React.js Conf! The tech industry is suffering from a lack of diversity, but it's important to us that we have a thriving community that is made up of people with a variety of experiences and viewpoints.
|
||||
|
||||
When we ran this program last year, we had *over 200* people apply for only 10 tickets. There were so many people that we wanted to bring in but we couldn't. The results were still awesome, and we had bright individuals from around the world attending who would have otherwise been unable to. These attendees took part in discussions at the conference and brought perspectives that we might not have otherwise seen there.
|
||||
|
||||
This year we're excited to bring back the scholarship, but we've set aside **40 tickets** because we really believe that it's important to do our best to make sure we have an even more diverse audience.
|
||||
|
||||
This is something I'm personally really excited to be a part of. I know the rest of the team is as well. We're really proud to have everyone at Facebook providing support and funding for this.
|
||||
|
||||
The details of the scholarship are provided below (or you can [go directly to the application](http://goo.gl/forms/PEmKj8oUp4)). I encourage you to apply! If you don't feel like you are eligible yourself, you can still help – send this along to friends, family, coworkers, acquaintances, or anybody who might be interested. And even if you haven't spoken before, please consider [submitting a proposal for a talk](http://conf.reactjs.com/) (either 30 minutes or just 5 minutes) - we're hoping to have a very diverse group of speakers in addition to attendees.
|
||||
|
||||
|
||||
- - -
|
||||
|
||||
Facebook is excited to announce that we are now accepting applications for the React.js Conf Diversity Scholarship!
|
||||
|
||||
Beginning today, those studying or working in computer science or a related field can apply for a partial scholarship to attend the React.js Conf in San Francisco, CA on February 22 & 23, 2016.
|
||||
|
||||
React opens a world of new possibilities such as server-side rendering, real-time updates, different rendering targets like SVG and canvas. React Native makes is easy to use the same concepts and technologies to build native mobile experiences on iOS and Android. Join us at React.js Conf to shape the future of client-side applications! For more information about the React.js conference, please see [the website](http://conf.reactjs.com/).
|
||||
|
||||
At Facebook, we believe that anyone anywhere can make a positive impact by developing products to make the world more open and connected to the people and things they care about. Given the current realities of the tech industry and the lack of representation of communities we seek to serve, applicants currently under-represented in Computer Science and related fields are strongly encouraged to apply. Facebook will make determinations on scholarship recipients in its sole discretion. Facebook complies with all equal opportunity laws.
|
||||
|
||||
To apply for the scholarship, please visit the application page: **<http://goo.gl/forms/PEmKj8oUp4>**
|
||||
|
||||
## Award Includes
|
||||
|
||||
* Paid registration fee for the React.js Conf Feburary 22 & 23 in downtown San Francisco, CA
|
||||
* Paid lodging expenses for February 21, 22, 23
|
||||
|
||||
## Important Dates
|
||||
|
||||
* Sunday December 13th 2015 - 11:59 PST: Applications for the React.js Conf Scholarship must be submitted in full
|
||||
* Wednesday, December 16th, 2015: Award recipients will be notified by email of their acceptance
|
||||
* Monday & Tuesday, February 22 & 23, 2016: React.js Conf
|
||||
|
||||
## Eligibility
|
||||
|
||||
* Must currently be studying or working in Computer Science or a related field
|
||||
* International applicants are welcome, but you will be responsible for securing your own visa to attend the conference
|
||||
* You must be able to provide your own transportation to San Francisco
|
||||
* You must be available to attend the full duration of React.js Conf on February 22 & 23 in San Francisco, CA
|
||||
80
docs/_posts/2015-12-16-ismounted-antipattern.md
Normal file
80
docs/_posts/2015-12-16-ismounted-antipattern.md
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: "isMounted is an Antipattern"
|
||||
author: jimfb
|
||||
---
|
||||
|
||||
As we move closer to officially deprecating isMounted, it's worth understanding why the function is an antipattern, and how to write code without the isMounted function.
|
||||
|
||||
The primary use case for `isMounted()` is to avoid calling `setState()` after a component has unmounted, because calling `setState()` after a component has unmounted will emit a warning. The “setState warning” exists to help you catch bugs, because calling `setState()` on an unmounted component is an indication that your app/component has somehow failed to clean up properly. Specifically, calling `setState()` in an unmounted component means that your app is still holding a reference to the component after the component has been unmounted - which often indicates a memory leak!
|
||||
|
||||
To avoid the error message, people often add lines like this:
|
||||
|
||||
```js
|
||||
if(this.isMounted()) { // This is bad.
|
||||
this.setState({...});
|
||||
}
|
||||
```
|
||||
|
||||
Checking `isMounted` before calling `setState()` does eliminate the warning, but it also defeats the purpose of the warning, since now you will never get the warning (even when you should!)
|
||||
|
||||
Other uses of `isMounted()` are similarly erroneous; using `isMounted()` is a code smell because the only reason you would check is because you think you might be holding a reference after the component has unmounted.
|
||||
|
||||
An easy migration strategy for anyone upgrading their code to avoid `isMounted()` is to track the mounted status yourself. Just set a `_isMounted` property to true in `componentDidMount` and set it to false in `componentWillUnmount`, and use this variable to check your component's status.
|
||||
|
||||
An optimal solution would be to find places where `setState()` might be called after a component has unmounted, and fix them. Such situations most commonly occur due to callbacks, when a component is waiting for some data and gets unmounted before the data arrives. Ideally, any callbacks should be canceled in `componentWillUnmount`, prior to unmounting.
|
||||
|
||||
For instance, if you are using a Flux store in your component, you must unsubscribe in `componentWillUnmount`:
|
||||
|
||||
```javascript{9}
|
||||
class MyComponent extends React.Component {
|
||||
componentDidMount() {
|
||||
mydatastore.subscribe(this);
|
||||
}
|
||||
render() {
|
||||
...
|
||||
}
|
||||
componentWillUnmount() {
|
||||
mydatastore.unsubscribe(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you use ES6 promises, you may need to wrap your promise in order to make it cancelable.
|
||||
|
||||
```js
|
||||
const cancelablePromise = makeCancelable(
|
||||
new Promise(r => component.setState({...}}))
|
||||
);
|
||||
|
||||
cancelablePromise
|
||||
.promise
|
||||
.then(() => console.log('resolved'))
|
||||
.catch((reason) => console.log('isCanceled', reason.isCanceled));
|
||||
|
||||
cancelablePromise.cancel(); // Cancel the promise
|
||||
```
|
||||
|
||||
Where `makeCancelable` is [defined by @istarkov](https://github.com/facebook/react/issues/5465#issuecomment-157888325) as:
|
||||
|
||||
```js
|
||||
const makeCancelable = (promise) => {
|
||||
let hasCanceled_ = false;
|
||||
|
||||
const wrappedPromise = new Promise((resolve, reject) => {
|
||||
promise.then((val) =>
|
||||
hasCanceled_ ? reject({isCanceled: true}) : resolve(val)
|
||||
);
|
||||
promise.catch((error) =>
|
||||
hasCanceled_ ? reject({isCanceled: true}) : reject(error)
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
promise: wrappedPromise,
|
||||
cancel() {
|
||||
hasCanceled_ = true;
|
||||
},
|
||||
};
|
||||
};
|
||||
```
|
||||
As an added bonus for getting your code cleaned up early, getting rid of `isMounted()` makes it one step easier for you to upgrade to ES6 classes, where using `isMounted()` is already prohibited. Happy coding!
|
||||
@@ -0,0 +1,383 @@
|
||||
---
|
||||
title: "React Components, Elements, and Instances"
|
||||
author: gaearon
|
||||
---
|
||||
|
||||
The difference between **components, their instances, and elements** confuses many React beginners. Why are there three different terms to refer to something that is painted on screen?
|
||||
|
||||
## Managing the Instances
|
||||
|
||||
If you’re new to React, you probably only worked with component classes and instances before. For example, you may declare a `Button` *component* by creating a class. When the app is running, you may have several *instances* of this component on screen, each with its own properties and local state. This is the traditional object-oriented UI programming. Why introduce *elements*?
|
||||
|
||||
In this traditional UI model, it is up to you to take care of creating and destroying child component instances. If a `Form` component wants to render a `Button` component, it needs to create its instance, and manually keep it up to date with any new information.
|
||||
|
||||
```js
|
||||
class Form extends TraditionalObjectOrientedView {
|
||||
render() {
|
||||
// Read some data passed to the view
|
||||
const { isSubmitted, buttonText } = this.attrs;
|
||||
|
||||
if (!isSubmitted && !this.button) {
|
||||
// Form is not yet submitted. Create the button!
|
||||
this.button = new Button({
|
||||
children: buttonText,
|
||||
color: 'blue'
|
||||
});
|
||||
this.el.appendChild(this.button.el);
|
||||
}
|
||||
|
||||
if (this.button) {
|
||||
// The button is visible. Update its text!
|
||||
this.button.attrs.children = buttonText;
|
||||
this.button.render();
|
||||
}
|
||||
|
||||
if (isSubmitted && this.button) {
|
||||
// Form was submitted. Destroy the button!
|
||||
this.el.removeChild(this.button.el);
|
||||
this.button.destroy();
|
||||
}
|
||||
|
||||
if (isSubmitted && !this.message) {
|
||||
// Form was submitted. Show the success message!
|
||||
this.message = new Message({ text: 'Success!' });
|
||||
this.el.appendChild(this.message.el);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is pseudocode, but it is more or less what you end up with when you write composite UI code that behaves consistently in an object-oriented way using a library like Backbone.
|
||||
|
||||
Each component instance has to keep references to its DOM node and to the instances of the children components, and create, update, and destroy them when the time is right. The lines of code grow as the square of the number of possible states of the component, and the parents have direct access to their children component instances, making it hard to decouple them in the future.
|
||||
|
||||
So how is React different?
|
||||
|
||||
## Elements Describe the Tree
|
||||
|
||||
In React, this is where the *elements* come to rescue. **An element is a plain object *describing* a component instance or DOM node and its desired properties.** It contains only information about the component type (for example, a `Button`), its properties (for example, its `color`), and any child elements inside it.
|
||||
|
||||
An element is not an actual instance. Rather, it is a way to tell React what you *want* to see on the screen. You can’t call any methods on the element. It’s just an immutable description object with two fields: `type: (string | ReactClass)` and `props: Object`[^1].
|
||||
|
||||
### DOM Elements
|
||||
|
||||
When an element’s `type` is a string, it represents a DOM node with that tag name, and `props` correspond to its attributes. This is what React will render. For example:
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-blue',
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This element is just a way to represent the following HTML as a plain object:
|
||||
|
||||
```html
|
||||
<button class='button button-blue'>
|
||||
<b>
|
||||
OK!
|
||||
</b>
|
||||
</button>
|
||||
```
|
||||
|
||||
Note how elements can be nested. By convention, when we want to create an element tree, we specify one or more child elements as the `children` prop of their containing element.
|
||||
|
||||
What’s important is that both child and parent elements are *just descriptions and not the actual instances*. They don’t refer to anything on the screen when you create them. You can create them and throw them away, and it won’t matter much.
|
||||
|
||||
React elements are easy to traverse, don’t need to be parsed, and of course they are much lighter than the actual DOM elements—they’re just objects!
|
||||
|
||||
### Component Elements
|
||||
|
||||
However, the `type` of an element can also be a function or a class corresponding to a React component:
|
||||
|
||||
```js
|
||||
{
|
||||
type: Button,
|
||||
props: {
|
||||
color: 'blue',
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is the core idea of React.
|
||||
|
||||
**An element describing a component is also an element, just like an element describing the DOM node. They can be nested and mixed with each other.**
|
||||
|
||||
This feature lets you define a `DangerButton` component as a `Button` with a specific `color` property value without worrying about whether `Button` renders to a DOM `<button>`, a `<div>`, or something else entirely:
|
||||
|
||||
```js
|
||||
const DangerButton = ({ children }) => ({
|
||||
type: Button,
|
||||
props: {
|
||||
color: 'red',
|
||||
children: children
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
You can mix and match DOM and component elements in a single element tree:
|
||||
|
||||
```js
|
||||
const DeleteAccount = () => ({
|
||||
type: 'div',
|
||||
props: {
|
||||
children: [{
|
||||
type: 'p',
|
||||
props: {
|
||||
children: 'Are you sure?'
|
||||
}
|
||||
}, {
|
||||
type: DangerButton,
|
||||
props: {
|
||||
children: 'Yep'
|
||||
}
|
||||
}, {
|
||||
type: Button,
|
||||
props: {
|
||||
color: 'blue',
|
||||
children: 'Cancel'
|
||||
}
|
||||
}]
|
||||
});
|
||||
```
|
||||
|
||||
Or, if you prefer JSX:
|
||||
|
||||
```js
|
||||
const DeleteAccount = () => (
|
||||
<div>
|
||||
<p>Are you sure?</p>
|
||||
<DangerButton>Yep</DangerButton>
|
||||
<Button color='blue'>Cancel</Button>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
This mix and matching helps keep components decoupled from each other, as they can express both *is-a* and *has-a* relationships exclusively through composition:
|
||||
|
||||
* `Button` is a DOM `<button>` with specific properties.
|
||||
* `DangerButton` is a `Button` with specific properties.
|
||||
* `DeleteAccount` contains a `Button` and a `DangerButton` inside a `<div>`.
|
||||
|
||||
### Components Encapsulate Element Trees
|
||||
|
||||
When React sees an element with a function or class `type`, it knows to ask *that* component what element it renders to, given the corresponding `props`.
|
||||
|
||||
When it sees this element:
|
||||
|
||||
```js
|
||||
{
|
||||
type: Button,
|
||||
props: {
|
||||
color: 'blue',
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
React will ask `Button` what it renders to. The `Button` will return this element:
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-blue',
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
React will repeat this process until it knows the underlying DOM tag elements for every component on the page.
|
||||
|
||||
React is like a child asking “what is Y” for every “X is Y” you explain to them until they figure out every little thing in the world.
|
||||
|
||||
Remember the `Form` example above? It can be written in React as follows[^1]:
|
||||
|
||||
```js
|
||||
const Form = ({ isSubmitted, buttonText }) => {
|
||||
if (isSubmitted) {
|
||||
// Form submitted! Return a message element.
|
||||
return {
|
||||
type: Message,
|
||||
props: {
|
||||
text: 'Success!'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Form is still visible! Return a button element.
|
||||
return {
|
||||
type: Button,
|
||||
props: {
|
||||
children: buttonText,
|
||||
color: 'blue'
|
||||
}
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
That’s it! For a React component, props are the input, and an element tree is the output.
|
||||
|
||||
**The returned element tree can contain both elements describing DOM nodes, and elements describing other components. This lets you compose independent parts of UI without relying on their internal DOM structure.**
|
||||
|
||||
We let React create, update, and destroy instances. We *describe* them with elements we return from the components, and React takes care of managing the instances.
|
||||
|
||||
### Components Can Be Classes or Functions
|
||||
|
||||
In the code above, `Form`, `Message`, and `Button` are React components. They can either be written as functions, like above, or as classes descending from `React.Component`. These three ways to declare a component are mostly equivalent:
|
||||
|
||||
```js
|
||||
// 1) As a function of props
|
||||
const Button = ({ children, color }) => ({
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-' + color,
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: children
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 2) Using the React.createClass() factory
|
||||
const Button = React.createClass({
|
||||
render() {
|
||||
const { children, color } = this.props;
|
||||
return {
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-' + color,
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: children
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// 3) As an ES6 class descending from React.Component
|
||||
class Button extends React.Component {
|
||||
render() {
|
||||
const { children, color } = this.props;
|
||||
return {
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-' + color,
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: children
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When a component is defined as a class, it is a little bit more powerful than a functional component. It can store some local state and perform custom logic when the corresponding DOM node is created or destroyed.
|
||||
|
||||
A functional component is less powerful but is simpler, and acts like a class component with just a single `render()` method. Unless you need features available only in a class, we encourage you to use functional components instead.
|
||||
|
||||
**However, whether functions or classes, fundamentally they are all components to React. They take the props as their input, and return the elements as their output.**
|
||||
|
||||
### Top-Down Reconciliation
|
||||
|
||||
When you call:
|
||||
|
||||
```js
|
||||
ReactDOM.render({
|
||||
type: Form,
|
||||
props: {
|
||||
isSubmitted: false,
|
||||
buttonText: 'OK!'
|
||||
}
|
||||
}, document.getElementById('root'));
|
||||
```
|
||||
|
||||
React will ask the `Form` component what element tree it returns, given those `props`. It will gradually “refine” its understanding of your component tree in terms of simpler primitives:
|
||||
|
||||
```js
|
||||
// React: You told me this...
|
||||
{
|
||||
type: Form,
|
||||
props: {
|
||||
isSubmitted: false,
|
||||
buttonText: 'OK!'
|
||||
}
|
||||
}
|
||||
|
||||
// React: ...And Form told me this...
|
||||
{
|
||||
type: Button,
|
||||
props: {
|
||||
children: 'OK!',
|
||||
color: 'blue'
|
||||
}
|
||||
}
|
||||
|
||||
// React: ...and Button told me this! I guess I'm done.
|
||||
{
|
||||
type: 'button',
|
||||
props: {
|
||||
className: 'button button-blue',
|
||||
children: {
|
||||
type: 'b',
|
||||
props: {
|
||||
children: 'OK!'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is a part of the process that React calls [reconciliation](/react/docs/reconciliation.html) which starts when you call [`ReactDOM.render()`](/react/docs/top-level-api.html#reactdom.render) or [`setState()`](/react/docs/component-api.html#setstate). By the end of the reconciliation, React knows the result DOM tree, and a renderer like `react-dom` or `react-native` applies the minimal set of changes necessary to update the DOM nodes (or the platform-specific views in case of React Native).
|
||||
|
||||
This gradual refining process is also the reason React apps are easy to optimize. If some parts of your component tree become too large for React to visit efficiently, you can tell it to [skip this “refining” and diffing certain parts of the tree if the relevant props have not changed](/react/docs/advanced-performance.html). It is very fast to calculate whether the props have changed if they are immutable, so React and immutability work great together, and can provide great optimizations with the minimal effort.
|
||||
|
||||
You might have noticed that this blog entry talks a lot about components and elements, and not so much about the instances. The truth is, instances have much less importance in React than in most object-oriented UI frameworks.
|
||||
|
||||
Only components declared as classes have instances, and you never create them directly: React does that for you. While [mechanisms for a parent component instance to access a child component instance](/react/docs/more-about-refs.html) exist, they are only used for imperative actions (such as setting focus on a field), and should generally be avoided.
|
||||
|
||||
React takes care of creating an instance for every class component, so you can write components in an object-oriented way with methods and local state, but other than that, instances are not very important in the React’s programming model and are managed by React itself.
|
||||
|
||||
## Summary
|
||||
|
||||
An *element* is a plain object describing what you want to appear on the screen in terms of the DOM nodes or other components. Elements can contain other elements in their props. Creating a React element is cheap. Once an element is created, it is never mutated.
|
||||
|
||||
A *component* can be declared in several different ways. It can be a class with a `render()` method. Alternatively, in simple cases, it can be defined as a function. In either case, it takes props as an input, and returns an element tree as the output.
|
||||
|
||||
When a component receives some props as an input, it is because a particular parent component returned an element with its `type` and these props. This is why people say that the props flows one way in React: from parents to children.
|
||||
|
||||
An *instance* is what you refer to as `this` in the component class you write. It is useful for [storing local state and reacting to the lifecycle events](/react/docs/component-api.html).
|
||||
|
||||
Functional components don’t have instances at all. Class components have instances, but you never need to create a component instance directly—React takes care of this.
|
||||
|
||||
Finally, to create elements, use [`React.createElement()`](/react/docs/top-level-api.html#react.createelement), [JSX](/react/docs/jsx-in-depth.html), or an [element factory helper](/react/docs/top-level-api.html#react.createfactory). Don’t write elements as plain objects in the real code—just know that they are plain objects under the hood.
|
||||
|
||||
## Further Reading
|
||||
|
||||
* [Introducing React Elements](/react/blog/2014/10/14/introducing-react-elements.html)
|
||||
* [Streamlining React Elements](/react/blog/2015/02/24/streamlining-react-elements.html)
|
||||
* [React (Virtual) DOM Terminology](/react/docs/glossary.html)
|
||||
|
||||
[^1]: All React elements require an additional ``$$typeof: Symbol.for('react.element')`` field declared on the object for [security reasons](https://github.com/facebook/react/pull/4832). It is omitted in the examples above. This blog entry uses inline objects for elements to give you an idea of what’s happening underneath but the code won’t run as is unless you either add `$$typeof` to the elements, or change the code to use `React.createElement()` or JSX.
|
||||
37
docs/_posts/2015-12-29-react-v0.14.4.md
Normal file
37
docs/_posts/2015-12-29-react-v0.14.4.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "React v0.14.4"
|
||||
author: spicyj
|
||||
---
|
||||
|
||||
Happy December! We have a minor point release today. It has just a few small bug fixes.
|
||||
|
||||
The release is now available for download:
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-0.14.4.js>
|
||||
Minified build for production: <https://fb.me/react-0.14.4.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-0.14.4.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-0.14.4.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-0.14.4.js>
|
||||
Minified build for production: <https://fb.me/react-dom-0.14.4.min.js>
|
||||
* **React DOM Server** (include React in the page before React DOM Server)
|
||||
Dev build with warnings: <https://fb.me/react-dom-server-0.14.4.js>
|
||||
Minified build for production: <https://fb.me/react-dom-server-0.14.4.min.js>
|
||||
|
||||
We've also published version `0.14.4` of the `react`, `react-dom`, and addons packages on npm and the `react` package on bower.
|
||||
|
||||
- - -
|
||||
|
||||
## Changelog
|
||||
|
||||
### React
|
||||
- Minor internal changes for better compatibility with React Native
|
||||
|
||||
### React DOM
|
||||
- The `autoCapitalize` and `autoCorrect` props are now set as attributes in the DOM instead of properties to improve cross-browser compatibility
|
||||
- Fixed bug with controlled `<select>` elements not handling updates properly
|
||||
|
||||
### React Perf Add-on
|
||||
- Some DOM operation names have been updated for clarity in the output of `.printDOM()`
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "(A => B) !=> (B => A)"
|
||||
author: jimfb
|
||||
---
|
||||
|
||||
The documentation for `componentWillReceiveProps` states that `componentWillReceiveProps` will be invoked when the props change as the result of a rerender. Some people assume this means "if `componentWillReceiveProps` is called, then the props must have changed", but that conclusion is logically incorrect.
|
||||
|
||||
The guiding principle is one of my favorites from formal logic/mathematics:
|
||||
> A implies B does not imply B implies A
|
||||
|
||||
Example: "If I eat moldy food, then I will get sick" does not imply "if I am sick, then I must have eaten moldy food". There are many other reasons I could be feeling sick. For instance, maybe the flu is circulating around the office. Similarly, there are many reasons that `componentWillReceiveProps` might get called, even if the props didn’t change.
|
||||
|
||||
If you don’t believe me, call `ReactDOM.render()` three times with the exact same props, and try to predict the number of times `componentWillReceiveProps` will get called:
|
||||
|
||||
|
||||
```js
|
||||
class Component extends React.Component {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
console.log('componentWillReceiveProps', nextProps.data.bar);
|
||||
}
|
||||
render() {
|
||||
return <div>Bar {this.props.data.bar}!</div>;
|
||||
}
|
||||
}
|
||||
|
||||
var container = document.getElementById('container');
|
||||
|
||||
var mydata = {bar: 'drinks'};
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
```
|
||||
|
||||
|
||||
In this case, the answer is "2". React calls `componentWillReceiveProps` twice (once for each of the two updates). Both times, the value of "drinks" is printed (ie. the props didn’t change).
|
||||
|
||||
To understand why, we need to think about what *could* have happened. The data *could* have changed between the initial render and the two subsequent updates, if the code had performed a mutation like this:
|
||||
|
||||
```js
|
||||
var mydata = {bar: 'drinks'};
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
mydata.bar = 'food'
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
mydata.bar = 'noise'
|
||||
ReactDOM.render(<Component data={mydata} />, container);
|
||||
```
|
||||
|
||||
React has no way of knowing that the data didn’t change. Therefore, React needs to call `componentWillReceiveProps`, because the component needs to be notified of the new props (even if the new props happen to be the same as the old props).
|
||||
|
||||
You might think that React could just use smarter checks for equality, but there are some issues with this idea:
|
||||
|
||||
* The old `mydata` and the new `mydata` are actually the same physical object (only the object’s internal value changed). Since the references are triple-equals-equal, doing an equality check doesn’t tell us if the value has changed. The only possible solution would be to have created a deep copy of the data, and then later do a deep comparison - but this can be prohibitively expensive for large data structures (especially ones with cycles).
|
||||
* The `mydata` object might contain references to functions which have captured variables within closures. There is no way for React to peek into these closures, and thus no way for React to copy them and/or verify equality.
|
||||
* The `mydata` object might contain references to objects which are re-instantiated during the parent's render (ie. not triple-equals-equal) but are conceptually equal (ie. same keys and same values). A deep-compare (expensive) could detect this, except that functions present a problem again because there is no reliable way to compare two functions to see if they are semantically equivalent.
|
||||
|
||||
Given the language constraints, it is sometimes impossible for us to achieve meaningful equality semantics. In such cases, React will call `componentWillReceiveProps` (even though the props might not have changed) so the component has an opportunity to examine the new props and act accordingly.
|
||||
|
||||
As a result, your implementation of `componentWillReceiveProps` MUST NOT assume that your props have changed. If you want an operation (such as a network request) to occur only when props have changed, your `componentWillReceiveProps` code needs to check to see if the props actually changed.
|
||||
|
||||
|
||||
10
docs/_posts/2016-01-12-discontinuing-ie8-support.md
Normal file
10
docs/_posts/2016-01-12-discontinuing-ie8-support.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "Discontinuing IE 8 Support in React DOM"
|
||||
author: spicyj
|
||||
---
|
||||
|
||||
Since its 2013 release, React has supported all popular browsers, including Internet Explorer 8 and above. We handle normalizing many quirks present in old browser versions, including event system differences, so that your app code doesn't have to worry about most browser bugs.
|
||||
|
||||
Today, Microsoft [discontinued support for older versions of IE](https://www.microsoft.com/en-us/WindowsForBusiness/End-of-IE-support). Starting with React v15, we're discontinuing React DOM's support for IE 8. We've heard that most React DOM apps already don't support old versions of Internet Explorer, so this shouldn't affect many people. This change will help us develop faster and make React DOM even better. (We won't actively remove IE 8–related code quite yet, but we will deprioritize new bugs that are reported. If you need to support IE 8 we recommend you stay on React v0.14.)
|
||||
|
||||
React DOM will continue to support IE 9 and above for the foreseeable future.
|
||||
60
docs/_posts/2016-02-19-new-versioning-scheme.md
Normal file
60
docs/_posts/2016-02-19-new-versioning-scheme.md
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "New Versioning Scheme"
|
||||
author: sebmarkbage
|
||||
---
|
||||
|
||||
Today we're announcing that we're switching to major revisions for React. The current version is 0.14.7. The next release will be: **15.0.0**
|
||||
|
||||
This change shouldn't materially affect most of you. Moving to major semver versions simply helps indicate our commitment to stability and gives us the flexibility to add new backwards-compatible features in minor releases. This means we can have fewer major releases and you won't have to wait as long to take advantage of improvements to React. Plus, if you're a component author, this versioning scheme gives you the flexibility to support two major versions of React at the same time so you don't need to leave anyone behind.
|
||||
|
||||
The core of the React API has been stable for years. Our business as well as many of yours all depend heavily on the use of React as a core piece of our infrastructure. We're committed to the stability as well as the progress of React going forward.
|
||||
|
||||
## Bring Everyone Along
|
||||
|
||||
React isn't just a library but an ecosystem. We know that your applications and ours are not just isolated islands of code. It is a network of your own application code, your own open source components and third party libraries that all depend on React.
|
||||
|
||||
<img src="/react/img/blog/versioning-1.png" width="403">
|
||||
|
||||
Therefore it is important that we don't just upgrade our own codebases but that we bring our whole community with us. We take the upgrade path very seriously - for everyone.
|
||||
|
||||
<img src="/react/img/blog/versioning-poll.png" width="596">
|
||||
|
||||
## Introducing Minor Releases
|
||||
|
||||
Ideally everyone could just depend on the latest version of React all the time.
|
||||
|
||||
<img src="/react/img/blog/versioning-2.png" width="463">
|
||||
|
||||
We know that in practice that is not possible. In the future, we expect more new additive APIs rather than breakage of existing ones. By moving to major revisions in the semver scheme, we can release new versions without breaking existing ones.
|
||||
|
||||
<img src="/react/img/blog/versioning-3.png" width="503">
|
||||
|
||||
That means that if one component needs a new API, there is no need for any of the other components to do any further work. They remain compatible.
|
||||
|
||||
## What Happened to 1.0.0?
|
||||
|
||||
Part of React's growth and popularity is that it is stable and performant in production. People have long asked what React v1.0 will look. Technically some breaking changes are important to avoid stagnating, but we still achieve stability by making it easy to upgrade. If major version numbers indicate API stability and engender trust that it can be used in production, then we got there a long time ago. There are too many preconceived notions of what v1.0 is. We're still following semver. We're just communicating stability by moving the 0 from the beginning to the end.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
Minor revision releases will include deprecation warnings and tips for how to upgrade an API or pattern that will be removed or changed in the future.
|
||||
|
||||
We will continue to release [codemods](https://www.youtube.com/watch?v=d0pOgY8__JM) for common patterns to make automatic upgrades of your codebase easier.
|
||||
|
||||
Once we've reached the end of life for a particular major version, we'll release a new major version where all deprecated APIs have been removed.
|
||||
|
||||
## Avoiding The Major Cliff
|
||||
|
||||
If you try to upgrade your component to 16.0.0 you might find that your application no longer works if you still have other dependencies. E.g. if Ryan's and Jed's components are only compatible with 15.x.x.
|
||||
|
||||
<img src="/react/img/blog/versioning-4.png" width="498">
|
||||
|
||||
Worst case, you revert back to 15.1.0 for your application. Since you'll want to use your component, you might also revert that one.
|
||||
|
||||
<img src="/react/img/blog/versioning-5.png" width="493">
|
||||
|
||||
Of course, Ryan and Jed think the same way. If we're not careful, we can hit a cliff where nobody upgrades. This has happened to many software project ecosystems in the past.
|
||||
|
||||
Therefore, we're committed to making it easy for most components and libraries built on top of React to be compatible with two major versions at the same time. We will do this by introducing new APIs before completely removing the old ones, thereby avoiding those cliffs.
|
||||
|
||||
<img src="/react/img/blog/versioning-6.png" width="493">
|
||||
96
docs/_posts/2016-03-07-react-v15-rc1.md
Normal file
96
docs/_posts/2016-03-07-react-v15-rc1.md
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
title: "React v15.0 Release Candidate"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
Sorry for the small delay in releasing this. As we said, we've been busy binge-watching House of Cards. That scene in the last episode where Francis and Claire Underwood <abbr title="You didn't think we would actually spoil anything did you?">████████████████████████████████████</abbr>. WOW!
|
||||
|
||||
But now we're ready, so without further ado, we're shipping a release candidate for React v15 now. As a reminder, [we're switching to major versions](/react/blog/2016/02/19/new-versioning-scheme.html) to indicate that we have been using React in production for a long time. This 15.0 release follows our previous 0.14 version and we'll continue to follow semver like we've been doing since 2013. It's also worth noting that [we no longer actively support Internet Explorer 8](/react/blog/2016/01/12/discontinuing-ie8-support.html). We believe React will work in its current form there but we will not be prioritizing any efforts to fix new issues that only affect IE8.
|
||||
|
||||
Please try it out before we publish the final release. Let us know if you run into any problems by filing issues on our [GitHub repo](https://github.com/facebook/react).
|
||||
|
||||
## Upgrade Guide
|
||||
|
||||
Like always, we have a few breaking changes in this release. We know changes can be painful (the Facebook codebase has over 15,000 React components), so we always try to make changes gradually in order to minimize the pain.
|
||||
|
||||
If your code is free of warnings when running under React 0.14, upgrading should be easy. The bulk of changes in this release are actually behind the scenes, impacting the way that React interacts with the DOM. The other substantial change is that React now supports the full range of SVG elements and attributes. Beyond that we have a large number of incremental improvements and additional warnings aimed to aid developers. We've also laid some groundwork in the core to bring you some new capabilities in future releases.
|
||||
|
||||
See the changelog below for more details.
|
||||
|
||||
## Installation
|
||||
|
||||
We recommend using React from `npm` and using a tool like browserify or webpack to build your code into a single bundle. To install the two packages:
|
||||
|
||||
* `npm install --save react@15.0.0-rc.1 react-dom@15.0.0-rc.1`
|
||||
|
||||
Remember that by default, React runs extra checks and provides helpful warnings in development mode. When deploying your app, set the `NODE_ENV` environment variable to `production` to use the production build of React which does not include the development warnings and runs significantly faster.
|
||||
|
||||
If you can’t use `npm` yet, we provide pre-built browser builds for your convenience, which are also available in the `react` package on bower.
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-15.0.0-rc.1.js>
|
||||
Minified build for production: <https://fb.me/react-15.0.0-rc.1.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-15.0.0-rc.1.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-15.0.0-rc.1.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-15.0.0-rc.1.js>
|
||||
Minified build for production: <https://fb.me/react-dom-15.0.0-rc.1.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 much more difficult to know if a website is using React, the advantage is that the DOM is much more lightweight. This change was made possible by us switching to use `document.createElement` on initial render. Previously we would generate a large string of HTML and then set `node.innerHTML`. At the time, this was decided to be faster than using `document.createElement` for the majority of cases and browsers that we supported. Browsers have continued to improve and so overwhelmingly this is no longer true. By using `createElement` we can make other parts of React faster. The ids were used to map back from events to the original React component, meaning we had to do a bunch of work on every event, even though we cached this data heavily. As we've all experienced, caching and in particularly invalidating caches, can be error prone and we saw many hard to reproduce issues over the years as a result. Now we can build up a direct mapping at render time since we already have a handle on the node.
|
||||
|
||||
- #### 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. Eg, in our most basic example on the home page we render `<div>Hello {this.props.name}</div>`, resulting in markup that contained 2 `<span>`s. Now we'll render plain text nodes interspersed with comment nodes that are used for demarcation. This gives us the same ability to update individual pieces of text, without creating extra nested nodes. Very few people have depended on the actual markup generated here so it's likely you are not impacted. However if you were targeting these `<span>`s in your CSS, you will need to adjust accordingly. You can always render them explicitly in your components.
|
||||
|
||||
- #### Rendering `null` now uses comment nodes
|
||||
|
||||
We've also made use of these comment nodes to change what `null` renders to. Rendering to `null` was a feature we added in React v0.11 and was implemented by rendering `<noscript>` elements. By rendering to comment nodes now, there's a chance some of your CSS will be targeting the wrong thing, specifically if you are making use of `:nth-child` selectors. This, along with the other changes mentioned above, have always been considered implementation details 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.
|
||||
|
||||
- #### Improved SVG support
|
||||
|
||||
All SVG tags and attributes 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 match their original capitalization and hyphenation as defined in the specification (ex: `gradientTransform` must be camel-cased but `clip-path` should be hyphenated).
|
||||
|
||||
|
||||
|
||||
### Breaking changes
|
||||
|
||||
It's worth calling out the DOM structure changes above again, in particular the change from `<span>`s. In the course of updating the Facebook codebase, we found a very small amount of code that was depending on the markup that React generated. Some of these cases were integration tests like WebDriver which were doing very specific XPath queries to target nodes. Others were simply tests using `ReactDOM.renderToStaticMarkup` and comparing markup. Again, there were a very small number of changes that had to be made, but we don't want anybody to be blindsided. We encourage everybody to run their test suites when upgrading and consider alternative approaches when possible. One approach that will work for some cases is to explicitly use `<span>`s in your `render` method.
|
||||
|
||||
These deprecations were introduced in v0.14 with a warning and the APIs are now removed.
|
||||
|
||||
- Deprecated APIs removed from `React`, specifically `findDOMNode`, `render`, `renderToString`, `renderToStaticMarkup`, and `unmountComponentAtNode`.
|
||||
- Deprecated APIs removed from `React.addons`, specifically `batchedUpdates` and `cloneWithProps`.
|
||||
- Deprecated APIs removed from component instances, specifically `setProps`, `replaceProps`, and `getDOMNode`.
|
||||
|
||||
### 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).
|
||||
|
||||
|
||||
### 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.
|
||||
- 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.)
|
||||
- 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.
|
||||
- Elements will now warn when attempting to read `ref` and `key` from the props.
|
||||
- React DOM now attempts to warn for mistyped event handlers on DOM elements (ex: `onclick` which should be `onClick`)
|
||||
|
||||
### Notable bug fixes
|
||||
|
||||
- Fixed multiple small memory leaks
|
||||
- Click events are handled by React DOM more reliably in mobile browsers, particularly in Mobile Safari.
|
||||
- Input events are handled more reliably in IE 10 and IE 11; spurious events no longer fire when using a placeholder.
|
||||
- React DOM now supports the `cite` and `profile` HTML attributes.
|
||||
- React DOM now supports the `onAnimationStart`, `onAnimationEnd`, `onAnimationIteration`, `onTransitionEnd`, and `onInvalid` events. Support for `onLoad` has been added to `object` elements.
|
||||
- Add-Ons: ReactTransitionGroup now correctly handles multiple nodes being removed simultaneously.
|
||||
- `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.
|
||||
- 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.
|
||||
32
docs/_posts/2016-03-16-react-v15-rc2.md
Normal file
32
docs/_posts/2016-03-16-react-v15-rc2.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: "React v15.0 Release Candidate 2"
|
||||
author: zpao
|
||||
---
|
||||
|
||||
Today we're releasing a second release candidate for version 15. Primarily this is to address 2 issues, but we also picked up a few small changes from new contributors, including some improvements to some of our new warnings.
|
||||
|
||||
The most pressing change that was made is to fix a bug in our new code that removes `<span>`s, as discussed in the original RC1 post. Specifically we have some code that takes a different path in IE11 and Edge due to the speed of some DOM operations. There was a bug in this code which didn't break out of the optimization for `DocumentFragment`s, resulting in text not appearing at all. Thanks to the several people who [reported this](https://github.com/facebook/react/issues/6246).
|
||||
|
||||
The other change is to our SVG code. In RC1 we had made the decision to pass through all attributes directly. This led to [some confusion with `class` vs `className`](https://github.com/facebook/react/issues/6211) and ultimately led us to reconsider our position on the approach. Passing through all attributes meant that we would have two different patterns for using React where things like hyphenated attributes would work for SVG but not HTML. In the future, we *might* change our approach to the problem for HTML as well but in the meantime, maintaining consistency is important. So we reverted the changes that allowed the attributes to be passed through and instead expanded the SVG property list to include all attributes that are in the spec. We believe we have everything now but definitely [let us know](https://github.com/facebook/react/issues/1657#issuecomment-197031403) if we missed anything. It was and still is our intent to support the full range of SVG tags and attributes in this release.
|
||||
|
||||
Thanks again to everybody who has tried the RC1 and reported issues. It has been extremely important and we wouldn't be able to do this without your help!
|
||||
|
||||
## 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@15.0.0-rc.2 react-dom@15.0.0-rc.2`
|
||||
|
||||
Remember that by default, React runs extra checks and provides helpful warnings in development mode. When deploying your app, set the `NODE_ENV` environment variable to `production` to use the production build of React which does not include the development warnings and runs significantly faster.
|
||||
|
||||
If you can’t use `npm` yet, we provide pre-built browser builds for your convenience, which are also available in the `react` package on bower.
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-15.0.0-rc.2.js>
|
||||
Minified build for production: <https://fb.me/react-15.0.0-rc.2.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-15.0.0-rc.2.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-15.0.0-rc.2.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-15.0.0-rc.2.js>
|
||||
Minified build for production: <https://fb.me/react-dom-15.0.0-rc.2.min.js>
|
||||
32
docs/_posts/2016-03-29-react-v0.14.8.md
Normal file
32
docs/_posts/2016-03-29-react-v0.14.8.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: "React v0.14.8"
|
||||
author: gaearon
|
||||
---
|
||||
|
||||
We have already released two release candidates for React 15, and the final version is coming soon.
|
||||
|
||||
However [Ian Christian Myers](https://github.com/iancmyers) discovered a memory leak related to server rendering in React 0.14 and [contributed a fix](https://github.com/facebook/react/pull/6060). While this memory leak has already been fixed in a different way in the React 15 release candidates, we decided to cut another 0.14 release that contains just this fix.
|
||||
|
||||
The release is now available for download:
|
||||
|
||||
* **React**
|
||||
Dev build with warnings: <https://fb.me/react-0.14.8.js>
|
||||
Minified build for production: <https://fb.me/react-0.14.8.min.js>
|
||||
* **React with Add-Ons**
|
||||
Dev build with warnings: <https://fb.me/react-with-addons-0.14.8.js>
|
||||
Minified build for production: <https://fb.me/react-with-addons-0.14.8.min.js>
|
||||
* **React DOM** (include React in the page before React DOM)
|
||||
Dev build with warnings: <https://fb.me/react-dom-0.14.8.js>
|
||||
Minified build for production: <https://fb.me/react-dom-0.14.8.min.js>
|
||||
* **React DOM Server** (include React in the page before React DOM Server)
|
||||
Dev build with warnings: <https://fb.me/react-dom-server-0.14.8.js>
|
||||
Minified build for production: <https://fb.me/react-dom-server-0.14.8.min.js>
|
||||
|
||||
We've also published version `0.14.8` of the `react`, `react-dom`, and addons packages on npm and the `react` package on bower.
|
||||
|
||||
- - -
|
||||
|
||||
## Changelog
|
||||
|
||||
### React
|
||||
- Fixed memory leak when rendering on the server
|
||||
@@ -16,4 +16,8 @@ We'd like to thank all of our contributors:
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
In addition, we're grateful to [Jeff Barczewski](https://github.com/jeffbski) for allowing us to use the [react](https://www.npmjs.com/package/react) package name on npm and to [Christopher Aue](http://christopheraue.net/) for letting us use the [reactjs.com](http://reactjs.com/) domain name and the [@reactjs](https://twitter.com/reactjs) username on Twitter. We'd also like to thank [ProjectMoon](https://github.com/ProjectMoon) for letting us use the [flux](https://www.npmjs.com/package/flux) package name on npm.
|
||||
In addition, we're grateful to
|
||||
- [Jeff Barczewski](https://github.com/jeffbski) for allowing us to use the [react](https://www.npmjs.com/package/react) package name on npm.
|
||||
- [Christopher Aue](http://christopheraue.net/) for letting us use the [reactjs.com](http://reactjs.com/) domain name and the [@reactjs](https://twitter.com/reactjs) username on Twitter.
|
||||
- [ProjectMoon](https://github.com/ProjectMoon) for letting us use the [flux](https://www.npmjs.com/package/flux) package name on npm.
|
||||
- Shane Anderson for allowing us to use the [react](https://github.com/react) org on GitHub.
|
||||
|
||||
@@ -9,7 +9,12 @@ id: all-posts
|
||||
<div class="inner-content">
|
||||
<h1>All Posts</h1>
|
||||
{% for page in site.posts %}
|
||||
<p><strong><a href="/react{{ page.url }}">{{ page.title }}</a></strong> on {{ page.date | date: "%B %e, %Y" }} by {{ page.author.name }}</p>
|
||||
<p><strong><a href="/react{{ page.url }}">{{ page.title }}</a></strong> on {{ page.date | date: "%B %e, %Y" }} by
|
||||
{% for author in page.authors %}
|
||||
{{ author.name }}
|
||||
{% if forloop.last == false %} and {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -129,7 +129,7 @@ h1, h2, h3, h4, h5, h6 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
li > a {
|
||||
box-sizing: content-box;
|
||||
padding: 0 10px;
|
||||
line-height: $navHeight;
|
||||
@@ -260,6 +260,22 @@ h1, h2, h3, h4, h5, h6 {
|
||||
&.active {
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
&.external {
|
||||
&:after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
padding-left: 5px;
|
||||
@include retina-image('../img/external', 10px 10px);
|
||||
background-position: 100% 0;
|
||||
background-repeat: no-repeat;
|
||||
font-size: 10px;
|
||||
line-height: 1em;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-docs-section {
|
||||
@@ -390,6 +406,39 @@ h1, h2, h3, h4, h5, h6 {
|
||||
@include clearfix;
|
||||
}
|
||||
|
||||
/* JSX Compiler */
|
||||
|
||||
.jsxCompiler {
|
||||
margin: 0 auto;
|
||||
padding-top: 20px;
|
||||
width: 1220px;
|
||||
|
||||
label.compiler-option {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
#jsxCompiler {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.playgroundPreview {
|
||||
padding: 0;
|
||||
width: 600px;
|
||||
word-wrap: break-word;
|
||||
|
||||
pre {
|
||||
@include code-typography;
|
||||
}
|
||||
}
|
||||
|
||||
.playgroundError {
|
||||
// The compiler view kills padding in order to render the CodeMirror code
|
||||
// more nicely. For the error view, put a padding back
|
||||
padding: 15px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-prev {
|
||||
float: left;
|
||||
}
|
||||
@@ -805,3 +854,72 @@ div[data-twttr-id] iframe {
|
||||
.three-column > ul:first-child {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
|
||||
/* Algolia Doc Search */
|
||||
|
||||
@media screen and (max-width: 960px) {
|
||||
#algolia-doc-search {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
input#algolia-doc-search {
|
||||
background: transparent url('/react/img/search.png') no-repeat 10px center;
|
||||
background-size: 16px 16px;
|
||||
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
margin-left: 10px;
|
||||
padding: 0 10px;
|
||||
padding-left: 35px;
|
||||
height: 30px;
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
background-color: #333;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
outline: none;
|
||||
width: 170px;
|
||||
|
||||
transition: width .2s ease;
|
||||
}
|
||||
|
||||
input#algolia-doc-search:focus {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.algolia-autocomplete .aa-dropdown-menu {
|
||||
margin-left: -110px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.algolia-autocomplete {
|
||||
vertical-align: top;
|
||||
height: 53px;
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion {
|
||||
border-bottom-color: #c05b4d;
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion--category-header {
|
||||
background-color: #cc7a6f;
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion--highlight {
|
||||
color: #c05b4d;
|
||||
}
|
||||
|
||||
.algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--highlight {
|
||||
background-color: #c05b4d;
|
||||
}
|
||||
|
||||
.aa-cursor .algolia-docsearch-suggestion--content {
|
||||
color: #c05b4d;
|
||||
}
|
||||
|
||||
.aa-cursor .algolia-docsearch-suggestion {
|
||||
background: #f1f3f5;
|
||||
}
|
||||
|
||||
28
docs/docs/01-why-react.de-DE.md
Normal file
28
docs/docs/01-why-react.de-DE.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
id: why-react-de-DE
|
||||
title: Warum React?
|
||||
permalink: why-react-de-DE.html
|
||||
---
|
||||
React ist eine JavaScript-Bibliothek von Facebook und Instagram für Benutzeroberflächen. Man kann sich React als das **V** in **[MVC](https://de.wikipedia.org/wiki/Model_View_Controller)** vorstellen.
|
||||
|
||||
Wir haben React für folgende Aufgabe entwickelt: **umfangreiche Anwendungen zu bauen, deren Daten sich zeitlich ändern**.
|
||||
|
||||
## Einfach
|
||||
|
||||
Beschreibe, wie sich Deine App zu jedem gewünschten Zeitpunkt präsentieren soll und React kümmert sich um alle Benutzeroberflächen-Änderungen sobald sich die zugrundeliegenden Daten ändern.
|
||||
|
||||
## Deklarativ
|
||||
|
||||
Bei Datenveränderungen drückt React bildlich die "Aktualisieren"-Taste und versteht sich darauf, nur die veränderten Elemente zu erneuern.
|
||||
|
||||
## Baue zusammensetzbare Komponenten
|
||||
|
||||
React unterstützt die Entwicklung wiederverwendbarer Komponenten. Tatsächlich machst Du in React nichts anderes, als Komponenten zu bauen. Dank ihrer Kapselung erleichtern Komponenten die Wiederverwendung und das Testen von Code sowie die Trennung der Belange.
|
||||
|
||||
## Gib' ihnen fünf Minuten
|
||||
|
||||
React hinterfragt eine ganze Reihe konventioneller Standpunkte. Auf den ersten Blick mögen einige Ideen verrückt klingen. [Gib' ihnen fünf Minuten](https://signalvnoise.com/posts/3124-give-it-five-minutes) während Du diese Anleitung liest; diese verrückten Ideen halfen dabei, tausende von Komponenten innerhalb und außerhalb von Facebook und Instagram zu entwickeln.
|
||||
|
||||
## Erfahre mehr
|
||||
|
||||
Erfahre mehr über unsere Motivation zur Entwicklung von React in [diesem Blogeintrag](/react/blog/2013/06/05/why-react.html).
|
||||
@@ -4,14 +4,13 @@ title: 为什么使用 React?
|
||||
permalink: why-react-zh-CN.html
|
||||
next: displaying-data-zh-CN.html
|
||||
---
|
||||
|
||||
React 是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 库。很人多认为 React 是 **[MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)** 中的 **V**(视图)。
|
||||
React 是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 库。很多人选择将 React 认为是 **[MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)** 中的 **V**(视图)。
|
||||
|
||||
我们创造 React 是为了解决一个问题:**构建随着时间数据不断变化的大规模应用程序**。
|
||||
|
||||
### 简单
|
||||
|
||||
仅仅只要表达出你的应用程序在任一个时间点应该长的样子,然后当底层的数据变了,React 会自动处理所有用户界面的更新。
|
||||
仅仅只要表达出你的应用程序在任一个时间点应该呈现的样子,然后当底层的数据变了,React 会自动处理所有用户界面的更新。
|
||||
|
||||
### 声明式 (Declarative)
|
||||
|
||||
@@ -28,5 +27,3 @@ React挑战了很多传统的知识,第一眼看上去可能很多想法有点
|
||||
## 了解更多
|
||||
|
||||
你可以从这篇[博客](/react/blog/2013/06/05/why-react.html)了解更多我们创造 React 的动机。
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ UI를 가지고 할 수 있는 가장 기초적인 것은 데이터를 표시하
|
||||
<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>
|
||||
@@ -54,7 +55,6 @@ setInterval(function() {
|
||||
}, 500);
|
||||
```
|
||||
|
||||
|
||||
## 반응 적(Reactive) 업데이트
|
||||
|
||||
`hello-react.html` 파일을 웹 브라우저에서 열어 당신의 이름을 텍스트 필드에 써 보세요. React는 단지 시간을 표시하는 부분만을 바꿉니다 — 텍스트 필드 안에 입력한 것은 그대로 남아 있구요, 당신이 이 동작을 관리하는 그 어떤 코드도 쓰지 않았음에도 불구하고 말이죠. React는 그걸 올바른 방법으로 알아서 해줍니다.
|
||||
@@ -63,7 +63,6 @@ setInterval(function() {
|
||||
|
||||
이 컴포넌트에 대한 입력은 `props` 라고 불립니다 — "properties" 를 줄인 것이죠. 그들은 JSX 문법에서는 어트리뷰트로서 전달됩니다. 당신은 `props` 를 컴포넌트 안에서 불변의(immutable) 엘리먼트로서 생각해야 하고, `this.props` 를 덮어씌우려고 해서는 안됩니다.
|
||||
|
||||
|
||||
## 컴포넌트들은 함수와 같습니다
|
||||
|
||||
React 컴포넌트들은 매우 단순합니다. 당신은 그것들을 `props` 와 `state` (이것들은 나중에 언급할 것입니다) 를 받고 HTML을 렌더링하는 단순한 함수들로 생각해도 됩니다. 이걸 염두하면, 컴포넌트의 작동을 이해하는 것도 쉽습니다.
|
||||
@@ -72,7 +71,6 @@ React 컴포넌트들은 매우 단순합니다. 당신은 그것들을 `props`
|
||||
>
|
||||
> **한가지 제약이 있습니다**: React 컴포넌트들은 단 하나의 루트 노드(root node)만을 렌더할 수 있습니다. 만약 여러개의 노드들을 리턴하고 싶다면, 그것들은 단 하나의 루트 노드로 싸여져 있어야만 합니다.
|
||||
|
||||
|
||||
## JSX 문법
|
||||
|
||||
우리는 컴포넌트를 사용하는 것이 "템플릿"과 "디스플레이 로직(display logic)"을 이용하는 것보다 관심을 분리(separate concerns)하는 데에 올바른 방법이라고 강하게 믿고 있습니다. 우리는 마크업과 그것을 만들어내는 코드는 친밀하게 함께 결합되어있다고 생각합니다. 또한, 디스플레이 로직은 종종 매우 복잡하고, 그것을 템플릿 언어를 이용해 표현하는 것은 점점 사용하기 어렵게 됩니다.
|
||||
@@ -91,12 +89,11 @@ JSX를 이용하면:
|
||||
|
||||
우리는 이것이 React 앱들을 만들기 쉽게 하고, 디자이너들이 이 문법을 더 선호하는 것을 발견했습니다, 하지만 모든 사람은 그들만의 선호하는 워크플로우가 있기 마련이므로, **JSX는 React를 사용하기 위해 필수적이지는 않습니다.**
|
||||
|
||||
JSX는 매우 작은 언어입니다. 그것을 배우고 싶다면, [JSX 깊게 살펴보기](/react/docs/jsx-in-depth-ko-KR.html). 를 살펴 보시기 바랍니다. 또는, [우리의 온라인 JSX 컴파일러](/react/jsx-compiler.html)를 통해 문법이 변환되는 것을 살펴 보시기 바랍니다.
|
||||
JSX는 매우 작은 언어입니다. 그것을 배우고 싶다면, [JSX 깊게 살펴보기](/react/docs/jsx-in-depth-ko-KR.html)를 살펴 보시기 바랍니다. 또는, [바벨 REPL](https://babeljs.io/repl/)를 통해 문법이 변환되는 것을 살펴 보시기 바랍니다.
|
||||
|
||||
JSX는 HTML과 비슷하지만, 완전히 똑같지는 않습니다. [JSX의 실수하기 쉬운 부분들](/react/docs/jsx-gotchas-ko-KR.html)에 중요한 차이점들에 대해 설명되어 있습니다.
|
||||
|
||||
JSX를 사용하기 시작하기 위한 가장 쉬운 방법은 브라우저에서 작동하는 `JSXTransformer`를 사용하는 것입니다. 우리는 이것을 프로덕션에서는 사용하지 않기를 강하게 권장하는 바입니다. 당신은 우리의 커맨드 라인 [react-tools](https://www.npmjs.com/package/react-tools) 패키지를 이용하여 미리 컴파일(precompile)해 사용할 수 있습니다.
|
||||
|
||||
[바벨에서 JSX를 시작하는 여러 방법을 제공합니다](http://babeljs.io/docs/setup/). 여기에는 커맨드 라인 툴부터 루비 온 레일스 연동까지 다양한 방법이 있습니다. 가장 편한 툴을 사용하세요.
|
||||
|
||||
## JSX 없이 React 사용하기
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ next: jsx-in-depth.html
|
||||
|
||||
The most basic thing you can do with a UI is display some data. React makes it easy to display data and automatically keeps the interface up-to-date when the data changes.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
Let's look at a really simple example. Create a `hello-react.html` file with the following code:
|
||||
@@ -20,6 +19,7 @@ Let's look at a really simple example. Create a `hello-react.html` file with the
|
||||
<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>
|
||||
@@ -55,7 +55,6 @@ setInterval(function() {
|
||||
}, 500);
|
||||
```
|
||||
|
||||
|
||||
## Reactive Updates
|
||||
|
||||
Open `hello-react.html` in a web browser and type your name into the text field. Notice that React is only changing the time string in the UI — any input you put in the text field remains, even though you haven't written any code to manage this behavior. React figures it out for you and does the right thing.
|
||||
@@ -64,7 +63,6 @@ The way we are able to figure this out is that React does not manipulate the DOM
|
||||
|
||||
The inputs to this component are called `props` — short for "properties". They're passed as attributes in JSX syntax. You should think of these as immutable within the component, that is, **never write to `this.props`**.
|
||||
|
||||
|
||||
## Components are Just Like Functions
|
||||
|
||||
React components are very simple. You can think of them as simple functions that take in `props` and `state` (discussed later) and render HTML. With this in mind, components are easy to reason about.
|
||||
@@ -73,7 +71,6 @@ React components are very simple. You can think of them as simple functions that
|
||||
>
|
||||
> **One limitation**: React components can only render a single root node. If you want to return multiple nodes they *must* be wrapped in a single root.
|
||||
|
||||
|
||||
## JSX Syntax
|
||||
|
||||
We strongly believe that components are the right way to separate concerns rather than "templates" and "display logic." We think that markup and the code that generates it are intimately tied together. Additionally, display logic is often very complex and using template languages to express it becomes cumbersome.
|
||||
@@ -98,7 +95,6 @@ JSX is similar to HTML, but not exactly the same. See [JSX gotchas](/react/docs/
|
||||
|
||||
[Babel exposes a number of ways to get started using JSX](http://babeljs.io/docs/setup/), ranging from command line tools to Ruby on Rails integrations. Choose the tool that works best for you.
|
||||
|
||||
|
||||
## React without JSX
|
||||
|
||||
JSX is completely optional; you don't have to use JSX with React. You can create React elements in plain JavaScript using `React.createElement`, which takes a tag name or component, a properties object, and variable number of optional child arguments.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
id: displaying-data-zh-CN
|
||||
title: 显示数据
|
||||
layout: docs
|
||||
permalink: displaying-data-zh-CN.html
|
||||
prev: why-react-zh-CN.html
|
||||
next: jsx-in-depth-zh-CN.html
|
||||
@@ -9,7 +8,6 @@ next: jsx-in-depth-zh-CN.html
|
||||
|
||||
用户界面能做的最基础的事就是显示一些数据。React 让显示数据变得简单,当数据变化的时候,用户界面会自动同步更新。
|
||||
|
||||
|
||||
## 开始
|
||||
|
||||
让我们看一个非常简单的例子。新建一个名为 `hello-react.html` 的文件,代码内容如下:
|
||||
@@ -21,6 +19,7 @@ next: jsx-in-depth-zh-CN.html
|
||||
<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>
|
||||
@@ -56,7 +55,6 @@ setInterval(function() {
|
||||
}, 500);
|
||||
```
|
||||
|
||||
|
||||
## 被动更新 (Reactive Updates)
|
||||
|
||||
在浏览器中打开 `hello-react.html` ,在输入框输入你的名字。你会发现 React 在用户界面中只改变了时间, 任何你在输入框输入的内容一直保留着,即使你没有写任何代码来完成这个功能。React 为你解决了这个问题,做了正确的事。
|
||||
@@ -65,7 +63,6 @@ setInterval(function() {
|
||||
|
||||
对这个组件的输入称为 `props` - "properties"的缩写。得益于 JSX 语法,它们通过参数传递。你必须知道在组件里,这些属性是不可改变的,也就是说 **`this.props` 是只读的**。
|
||||
|
||||
|
||||
## 组件就像是函数
|
||||
|
||||
React 组件非常简单。你可以认为它们就是简单的函数,接受 `props` 和 `state` (后面会讨论) 作为参数,然后渲染出 HTML。正是应为它们是这么的简单,这使得它们非常容易理解。
|
||||
@@ -74,12 +71,13 @@ React 组件非常简单。你可以认为它们就是简单的函数,接受 `
|
||||
>
|
||||
> **只有一个限制**: React 组件只能渲染单个根节点。如果你想要返回多个节点,它们*必须*被包含在同一个节点里。
|
||||
|
||||
|
||||
## JSX 语法
|
||||
|
||||
我们坚信组件是正确方法去做关注分离,而不是通过“模板”和“展示逻辑”。我们认为标签和生成它的代码是紧密相连的。此外,展示逻辑通常是很复杂的,通过模板语言实现这些逻辑会产生大量代码。
|
||||
|
||||
我们得出解决这个问题最好的方案是通过 JavaScript 直接生成模板,这样你就可以用一个真正语言的所有表达能力去构建用户界面。为了使这变得更简单,我们做了一个非常简单、**可选**类似 HTML 语法 ,通过函数调用即可生成模板的编译器,称为 JSX。
|
||||
我们得出解决这个问题最好的方案是通过 JavaScript 直接生成模板,这样你就可以用一个真正语言的所有表达能力去构建用户界面。
|
||||
|
||||
为了使这变得更简单,我们做了一个非常简单、**可选**类似 HTML 语法 ,通过函数调用即可生成模板的编译器,称为 JSX。
|
||||
|
||||
**JSX 让你可以用 HTML 语法去写 JavaScript 函数调用** 为了在 React 生成一个链接,通过纯 JavaScript 你可以这么写:
|
||||
|
||||
@@ -95,16 +93,16 @@ JSX 非常小;上面“hello, world”的例子使用了 JSX 所有的特性
|
||||
|
||||
JSX 类似于 HTML,但不是完全一样。参考 [JSX 陷阱](/react/docs/jsx-gotchas-zh-CN.html) 学习关键区别。
|
||||
|
||||
最简单开始学习 JSX 的方法就是使用浏览器端的 `JSXTransformer`。我们强烈建议你不要在生产环境中使用它。你可以通过我们的命令行工具 [react-tools](https://www.npmjs.com/package/react-tools) 包来预编译你的代码。
|
||||
|
||||
[Babel 公开了一些使用 JSX 的方式],从命令行工具到 Ruby on Rails 集成。选择一个对你来说最合适的工具。
|
||||
|
||||
## 没有 JSX 的 React
|
||||
|
||||
你完全可以选择是否使用 JSX,并不是 React 必须的。你可以通过 `React.createElement` 来创建一个树。第一个参数是标签,第二个参数是一个属性对象,每三个是子节点。
|
||||
JSX完全是可选的;你无需在 React 中必须使用 JSX。你可以通过 `React.createElement` 来创建一个树。第一个参数是标签,第二个参数是一个属性对象,第三个是子节点。
|
||||
|
||||
```javascript
|
||||
var child = React.createElement('li', null, 'Text Content');
|
||||
var root = React.createElement('ul', { className: 'my-list' }, child);
|
||||
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'));
|
||||
```
|
||||
|
||||
@@ -121,6 +119,6 @@ React 已经为 HTML 标签提供内置工厂方法。
|
||||
|
||||
```javascript
|
||||
var root = React.DOM.ul({ className: 'my-list' },
|
||||
React.DOM.li(null, 'Text Content')
|
||||
);
|
||||
React.DOM.li(null, 'Text Content')
|
||||
);
|
||||
```
|
||||
|
||||
@@ -216,4 +216,4 @@ var content = (
|
||||
```
|
||||
|
||||
> 注意:
|
||||
> JSXはHTMLに似ていますが、全く同じではありません。いくつかのキーの違いについては[JSXの理解](/react/docs/jsx-gotchas.html) をご覧ください。
|
||||
> JSXはHTMLに似ていますが、全く同じではありません。いくつかのキーの違いについては[JSXの理解](/react/docs/jsx-gotchas.html) をご覧ください。
|
||||
|
||||
@@ -83,7 +83,7 @@ var Nav = React.createClass({ });
|
||||
var Nav = React.createClass({displayName: "Nav", });
|
||||
```
|
||||
|
||||
[JSX 컴파일러](/react/jsx-compiler.html)를 보면 JSX에서 어떻게 네이티브 JavaScript로 변환(desugars)하는지 볼 수 있고, [HTML-JSX 변환기](/react/html-jsx.html)는 이미 있는 HTML을 JSX로 변환해 줍니다.
|
||||
[바벨 REPL](https://babeljs.io/repl/)를 보면 JSX에서 어떻게 네이티브 JavaScript로 변환(desugars)하는지 볼 수 있고, [HTML-JSX 변환기](/react/html-jsx.html)는 이미 있는 HTML을 JSX로 변환해 줍니다.
|
||||
|
||||
JSX를 사용 하시려면, [시작하기](/react/docs/getting-started-ko-KR.html) 가이드에서 어떻게 컴파일을 하기 위해 설정하는지 보실 수 있습니다.
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ It doesn't alter the semantics of JavaScript.
|
||||
|
||||
React can either render HTML tags (strings) or React components (classes).
|
||||
|
||||
To render a HTML tag, just use lower-case tag names in JSX:
|
||||
To render an HTML tag, just use lower-case tag names in JSX:
|
||||
|
||||
```javascript
|
||||
var myDivElement = <div className="foo" />;
|
||||
@@ -82,10 +82,7 @@ var Nav = React.createClass({ });
|
||||
var Nav = React.createClass({displayName: "Nav", });
|
||||
```
|
||||
|
||||
Use the [Babel REPL](https://babeljs.io/repl/) to try out JSX and see how it
|
||||
desugars into native JavaScript, and the
|
||||
[HTML to JSX converter](/react/html-jsx.html) to convert your existing HTML to
|
||||
JSX.
|
||||
Use the [Babel REPL](https://babeljs.io/repl/) to try out JSX and see how it desugars into native JavaScript, and the [HTML to JSX converter](/react/html-jsx.html) to convert your existing HTML to JSX.
|
||||
|
||||
If you want to use JSX, the [Getting Started](/react/docs/getting-started.html) guide shows how to set up compilation.
|
||||
|
||||
@@ -163,8 +160,7 @@ var App = (
|
||||
|
||||
### Attribute Expressions
|
||||
|
||||
To use a JavaScript expression as an attribute value, wrap the expression in a
|
||||
pair of curly braces (`{}`) instead of quotes (`""`).
|
||||
To use a JavaScript expression as an attribute value, wrap the expression in a pair of curly braces (`{}`) instead of quotes (`""`).
|
||||
|
||||
```javascript
|
||||
// Input (JSX):
|
||||
|
||||
@@ -8,7 +8,6 @@ next: jsx-spread-zh-CN.html
|
||||
|
||||
[JSX](https://facebook.github.io/jsx/) 是一个看起来很像 XML 的 JavaScript 语法扩展。React 可以用来做简单的 JSX 句法转换。
|
||||
|
||||
|
||||
## 为什么要用 JSX?
|
||||
|
||||
你不需要为了 React 使用 JSX,可以直接使用原生 JS。但是,我们建议使用 JSX 是因为它能精确,也是常用的定义包含属性的树状结构的语法。
|
||||
@@ -46,7 +45,6 @@ React 的 JSX 使用大、小写的约定来区分本地组件的类和 HTML 标
|
||||
> 由于 JSX 就是 JavaScript,一些标识符像 `class` 和 `for` 不建议作为 XML
|
||||
> 属性名。作为替代,React DOM 使用 `className` 和 `htmlFor` 来做对应的属性。
|
||||
|
||||
|
||||
## 转换(Transform)
|
||||
|
||||
JSX 把类 XML 的语法转成原生 JavaScript,XML 元素、属性和子节点被转换成 `React.createElement` 的参数。
|
||||
@@ -90,6 +88,7 @@ var Nav = React.createClass({displayName: "Nav", });
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> JSX 表达式总是会当作 ReactElement 执行。具体的实际细节可能不同。一种优化
|
||||
> 的模式是把 ReactElement 当作一个行内的对象字面量形式来绕过
|
||||
> `React.createElement` 里的校验代码。
|
||||
@@ -99,7 +98,7 @@ var Nav = React.createClass({displayName: "Nav", });
|
||||
如果你正在构建一个有很多子组件的组件,比如表单,你也许会最终得到许多的变量声明。
|
||||
|
||||
```javascript
|
||||
// 尴尬的变量声明块
|
||||
// 尴尬的变量声明块
|
||||
var Form = MyFormComponent;
|
||||
var FormRow = Form.Row;
|
||||
var FormLabel = Form.Label;
|
||||
@@ -221,5 +220,5 @@ var content = (
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> JSX 类似于 HTML,但不完全一样。参考 [JSX 陷阱](/react/docs/jsx-gotchas-zh-CN.html) 了解主要不同。
|
||||
|
||||
@@ -12,7 +12,7 @@ next: jsx-gotchas-ko-KR.html
|
||||
var component = <Component foo={x} bar={y} />;
|
||||
```
|
||||
|
||||
## Props의 변경은 나빠요.[^1]
|
||||
## Props의 변경은 나빠요
|
||||
|
||||
하지만 어떤 프로퍼티를 설정하고 싶은지 모른다면, 객체 레이어에 넣고 싶어질 수도 있습니다.
|
||||
|
||||
@@ -50,7 +50,3 @@ props는 변하지 않는 것으로 간주해야 합니다. props 객체를 변
|
||||
## 이상한 `...` 표기법은 무엇인가요?
|
||||
|
||||
`...` 연산자(스프레드 연산자)는 이미 [ES6의 배열](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator)에서 지원합니다. [객체 rest와 스프레드 프로퍼티](https://github.com/sebmarkbage/ecmascript-rest-spread)에 대한 ES7의 제안도 있습니다. JSX의 구문을 더 깔끔하게 하기 위해 지원되고 개발중인 표준을 활용하고 있습니다.
|
||||
|
||||
[^1]: 아무래도 좋지만, 이 제목의 원문 "Mutating Props is Bad, mkay"는 사우스 파크에
|
||||
나온 대사 "[Drug is bad, mkay](https://www.youtube-nocookie.com/watch?v=Uh7l8dx-h8M)"의
|
||||
패러디입니다.
|
||||
|
||||
@@ -12,7 +12,7 @@ If you know all the properties that you want to place on a component ahead of ti
|
||||
var component = <Component foo={x} bar={y} />;
|
||||
```
|
||||
|
||||
## Mutating Props is Bad, mkay
|
||||
## Mutating Props is Bad
|
||||
|
||||
If you don't know which properties you want to set, you might be tempted to add them onto the object later:
|
||||
|
||||
@@ -49,4 +49,4 @@ You can use this multiple times or combine it with other attributes. The specifi
|
||||
|
||||
## What's with the weird `...` notation?
|
||||
|
||||
The `...` operator (or spread operator) is already supported for [arrays in ES6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator). There is also an ES7 proposal for [Object Rest and Spread Properties](https://github.com/sebmarkbage/ecmascript-rest-spread). We're taking advantage of these supported and developing standards in order to provide a cleaner syntax in JSX.
|
||||
The `...` operator (or spread operator) is already supported for [arrays in ES6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator). There is also an ECMAScript proposal for [Object Rest and Spread Properties](https://github.com/sebmarkbage/ecmascript-rest-spread). We're taking advantage of these supported and developing standards in order to provide a cleaner syntax in JSX.
|
||||
|
||||
@@ -12,7 +12,6 @@ next: jsx-gotchas-zh-CN.html
|
||||
var component = <Component foo={x} bar={y} />;
|
||||
```
|
||||
|
||||
|
||||
## 修改 Props 是不好的,明白吗
|
||||
|
||||
如果你不知道要设置哪些 Props,那么现在最好不要设置它:
|
||||
@@ -27,7 +26,6 @@ next: jsx-gotchas-zh-CN.html
|
||||
|
||||
Props 应该被认为是不可变的。在别处修改 props 对象可能会导致预料之外的结果,所以原则上这将是一个冻结的对象。
|
||||
|
||||
|
||||
## 展开属性(Spread Attributes)
|
||||
|
||||
现在你可以使用 JSX 的新特性 - 展开属性:
|
||||
@@ -49,7 +47,6 @@ Props 应该被认为是不可变的。在别处修改 props 对象可能会导
|
||||
console.log(component.props.foo); // 'override'
|
||||
```
|
||||
|
||||
|
||||
## 这个奇怪的 `...` 标记是什么?
|
||||
|
||||
这个 `...` 操作符(增强的操作符)已经被 [ES6 数组](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) 支持。相关的还有 ES7 规范草案中的 [Object 剩余和展开属性(Rest and Spread Properties)](https://github.com/sebmarkbage/ecmascript-rest-spread)。我们利用了这些还在制定中标准中已经被支持的特性来使 JSX 拥有更优雅的语法。
|
||||
这个 `...` 操作符(增强的操作符)已经被 [ES6 数组](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) 支持。相关的还有 ECMAScript 规范草案中的 [Object 剩余和展开属性(Rest and Spread Properties)](https://github.com/sebmarkbage/ecmascript-rest-spread)。我们利用了这些还在制定中标准中已经被支持的特性来使 JSX 拥有更优雅的语法。
|
||||
|
||||
@@ -27,7 +27,7 @@ If you want to display an HTML entity within dynamic content, you will run into
|
||||
<div>{'First · Second'}</div>
|
||||
```
|
||||
|
||||
There are various ways to work-around this issue. The easiest one is to write unicode characters directly in JavaScript. You need to make sure that the file is saved as UTF-8 and that the proper UTF-8 directives are set so the browser will display it correctly.
|
||||
There are various ways to work-around this issue. The easiest one is to write Unicode characters directly in JavaScript. You need to make sure that the file is saved as UTF-8 and that the proper UTF-8 directives are set so the browser will display it correctly.
|
||||
|
||||
```javascript
|
||||
<div>{'First · Second'}</div>
|
||||
@@ -61,6 +61,12 @@ If you pass properties to native HTML elements that do not exist in the HTML spe
|
||||
<div data-custom-attribute="foo" />
|
||||
```
|
||||
|
||||
However, arbitrary attributes are supported on custom elements (those with a hyphen in the tag name or an `is="..."` attribute).
|
||||
|
||||
```javascript
|
||||
<x-my-component custom-attribute="foo" />
|
||||
```
|
||||
|
||||
[Web Accessibility](http://www.w3.org/WAI/intro/aria) attributes starting with `aria-` will be rendered properly.
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -52,6 +52,7 @@ HTML 实体可以插入到 JSX 的文本中。
|
||||
<div dangerouslySetInnerHTML={{'{{'}}__html: 'First · Second'}} />
|
||||
```
|
||||
|
||||
|
||||
## 自定义 HTML 属性
|
||||
|
||||
如果往原生 HTML 元素里传入 HTML 规范里不存在的属性,React 不会显示它们。如果需要使用自定义属性,要加 `data-` 前缀。
|
||||
@@ -60,6 +61,12 @@ HTML 实体可以插入到 JSX 的文本中。
|
||||
<div data-custom-attribute="foo" />
|
||||
```
|
||||
|
||||
然而,在自定义元素中任意的属性都是被支持的 (那些在tag名里带有连接符或者 `is="..."` 属性的)
|
||||
|
||||
```javascript
|
||||
<x-my-component custom-attribute="foo" />
|
||||
```
|
||||
|
||||
以 `aria-` 开头的 [网络无障碍](http://www.w3.org/WAI/intro/aria) 属性可以正常使用。
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -78,7 +78,7 @@ Reactがデータの変更を通知する共通な方法は `setState(data, call
|
||||
|
||||
`this.state` UIのstateを表す必要がある最小限の量のデータだけを保持するべきです。このような点で以下のようなものは保持するべきではありません。
|
||||
|
||||
* **計算されたデータ:**
|
||||
* **計算されたデータ:**
|
||||
stateに基づく事前に計算された値について心配は要りません。 `render()` を用いて、全ての計算を行って、UIの一貫性を保証するよりも簡単です。例えば、stateにリスト化されたアイテムの配列を持っていて、文字列としてその数をレンダリングしたいとして、それらをstateに保持するよりも `render()` メソッドに `this.state.listItems.length + ' list items'` を単純にレンダリングすれば良いのです。
|
||||
* **Reactのコンポーネント:** 隠れたpropsとstateに基づいて `render()` でそれらをビルドしてください。
|
||||
* **propsからコピーしたデータ:** 可能であれば、propsを真のソースとして使ってみてください。propsは時とともに変化し得るので、正しくstateにpropsを保持する使い方は、以前の値を知っていることになり得ます。
|
||||
* **propsからコピーしたデータ:** 可能であれば、propsを真のソースとして使ってみてください。propsは時とともに変化し得るので、正しくstateにpropsを保持する使い方は、以前の値を知っていることになり得ます。
|
||||
|
||||
@@ -8,7 +8,6 @@ next: multiple-components-ko-KR.html
|
||||
|
||||
이미 React에서 [어떻게 데이터를 표시](/react/docs/displaying-data-ko-KR.html)하는지를 배웠습니다. 이제 UI와의 상호작용을 어떻게 만드는지 살펴보죠.
|
||||
|
||||
|
||||
## 간단한 예제
|
||||
|
||||
```javascript
|
||||
@@ -35,34 +34,29 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 이벤트 핸들링과 통합적인(Synthetic) 이벤트
|
||||
|
||||
React에서의 이벤트 핸들러는 HTML에서 그러던 것처럼 간단히 카멜케이스 프로퍼티(camelCased prop)로 넘기면 됩니다. React의 모든 이벤트는 통합적인 이벤트 시스템의 구현으로 IE8 이상에서는 같은 행동이 보장됩니다. 즉, React는 사양에 따라 어떻게 이벤트를 일으키고(bubble) 잡는지 알고 있고, 당신이 사용하는 브라우저와 관계없이 이벤트 핸들러에 전달되는 이벤트는 [W3C 사양](http://www.w3.org/TR/DOM-Level-3-Events/)과 같도록 보장됩니다.
|
||||
|
||||
|
||||
## 기본 구현: 오토바인딩과 이벤트 델리게이션
|
||||
<a name="under-the-hood-autobinding-and-event-delegation"></a>
|
||||
|
||||
코드를 고성능으로 유지하고 이해하기 쉽게 하기 위해, React는 보이지 않는 곳에서 몇 가지 일을 수행합니다.
|
||||
|
||||
**오토바인딩:** JavaScript에서 콜백을 만들 때, 보통은 `this`의 값이 정확하도록 명시적으로 메소드를 인스턴스에 바인드해야 합니다. React에서는 모든 메소드가 자동으로 React의 컴포넌트 인스턴스에 바인드됩니다. React가 바인드 메소드를 캐시하기 때문에 매우 CPU와 메모리에 효율적입니다. 타이핑해야 할 것도 줄어들죠!
|
||||
**오토바인딩:** JavaScript에서 콜백을 만들 때, 보통은 `this`의 값이 정확하도록 명시적으로 메소드를 인스턴스에 바인드해야 합니다. React에서는 모든 메소드가 자동으로 React의 컴포넌트 인스턴스에 바인드됩니다.(ES6 클래스 문법을 사용할 때는 재외하고) React가 바인드 메소드를 캐시하기 때문에 매우 CPU와 메모리에 효율적입니다. 타이핑해야 할 것도 줄어들죠!
|
||||
|
||||
**이벤트 델리게이션:** React는 실제로는 노드자신에게 이벤트 핸들러를 붙이지 않습니다. React가 시작되면 React는 탑 레벨의 단일 이벤트 리스너로 모든 이벤트를 리스닝하기 시작합니다. 컴포넌트가 마운트되거나 언마운트 될 때, 이벤트 핸들러는 그냥 내부 매핑에서 넣거나 뺄 뿐입니다. 이벤트가 발생하면, React는 이 매핑을 사용해서 어떻게 디스패치할 지를 알게 됩니다. 매핑에 이벤트 핸들러가 남아있지 않으면, React의 이벤트 핸들러는 그냥 아무것도 하지 않습니다. 왜 이 방식이 빠른지 더 알고 싶으시면, [David Walsh의 멋진 블로그 글](http://davidwalsh.name/event-delegate)을 읽어 보세요.
|
||||
|
||||
|
||||
## 컴포넌트는 그냥 state 머신일 뿐
|
||||
|
||||
React는 UI를 간단한 state 머신이라 생각합니다. UI를 다양한 state와 그 state의 렌더링으로 생각함으로써 UI를 일관성 있게 관리하기 쉬워집니다.
|
||||
|
||||
React에서는, 간단히 컴포넌트의 state를 업데이트하고, 이 새로운 state의 UI를 렌더링합니다. React는 DOM의 변경을 가장 효율적인 방법으로 관리해줍니다.
|
||||
|
||||
|
||||
## state의 동작 원리
|
||||
|
||||
React에게 데이터의 변경을 알리는 일반적인 방법은 `setState(data, callback)`을 호출하는 것입니다. 이 메소드는 `this.state`에 `data`를 머지하고 컴포넌트를 다시 렌더링 합니다. 컴포넌트의 재-렌더링이 끝나면, 생략가능한 `callback`이 호출됩니다. 대부분의 경우 React가 UI를 최신상태로 유지해주기 때문에 `callback`을 사용할 필요가 없습니다.
|
||||
|
||||
|
||||
## 어떤 컴포넌트가 state를 가져야 할까요?
|
||||
|
||||
대부분의 컴포넌트는 `props`로부터 데이터를 받아 렌더할 뿐입니다만, 가끔 유저 인풋, 서버 요청, 시간의 경과에 반응해야 할 필요가 있습니다. 이럴 때 state를 사용합니다.
|
||||
@@ -71,7 +65,6 @@ React에게 데이터의 변경을 알리는 일반적인 방법은 `setState(da
|
||||
|
||||
일반적인 패턴은 데이터만 렌더하는 여러 상태를 가지지 않은 컴포넌트를 만들고, 그 위에 상태기반(stateful) 컴포넌트를 만들어 계층 안의 자식 컴포넌트에게 `props`를 통해 state를 전달하는 것입니다. state를 가지지 않은 컴포넌트가 선언적인 방법으로 데이터를 렌더링 하는 동안, 상태기반 컴포넌트는 모든 상호작용 로직을 캡슐화합니다.
|
||||
|
||||
|
||||
## state를 어떻게 *써야* 할까요?
|
||||
|
||||
**state는 컴포넌트의 이벤트 핸들러에 의해 UI 업데이트를 트리거할때 변경될 가능성이 있어, 그때 사용할 데이터를 가져야 합니다.** 실제 앱에서는 이 데이터는 매우 작고 JSON 직렬화 가능한 경향이 있습니다. 상태기반 컴포넌트를 만들때, 가능한 작게 state를 서술하고 `this.state`에만 저장하도록 해보세요. 그냥 `render()` 안에서 이 state를 기반으로 다른 모든 정보를 계산합니다. 이 방식으로 애플리케이션을 작성하고 생각하면 가장 최적의 애플리케이션으로 발전해가는 경향이 있다는 것을 발견하게 될 것입니다. 꼭 필요하지 않은 값이나 계산된 값을 state에 추가하는 것은 render가 그것을 계산하는 대신에 명시적으로 그것들을 맞춰줘야 하는 것을 의미하기 때문이죠.
|
||||
@@ -82,4 +75,4 @@ React에게 데이터의 변경을 알리는 일반적인 방법은 `setState(da
|
||||
|
||||
* **계산된 데이터:** state에 따라 값을 미리 계산하는 것에 대해 염려하지 마세요. 계산은 모두 `render()`에서 하는 것이 UI의 일관성을 유지하기 쉽습니다. 예를 들어, state에서 list items 배열을 가지고 있고 문자열으로 카운트를 렌더링 할 경우, state에 저장하기보다는 그냥 `render()` 메소드안에서 `this.state.listItems.length + ' list items'`를 렌더하세요.
|
||||
* **React 컴포넌트:** 가지고 있는 props와 state로 `render()`안에서 만드세요.
|
||||
* **props에서 복사한 데이터:** 가능한 한 원래의 소스로 props를 사용하도록 해보세요. props를 state에 저장하는 단 하나의 올바른 사용법은 이전 값을 알고 싶을 때입니다. props는 시간이 지나면 변경될 수도 있기 때문이죠.
|
||||
* **props에서 복사한 데이터:** 가능한 한 원래의 소스로 props를 사용하도록 해보세요. props를 state에 저장하는 단 하나의 올바른 사용법은 이전 값을 알고 싶을 때입니다. props는 부모 컴포넌트의 재 렌더링의 결과 변경될 수도 있기 때문이죠.
|
||||
|
||||
@@ -8,7 +8,6 @@ next: multiple-components.html
|
||||
|
||||
You've already [learned how to display data](/react/docs/displaying-data.html) with React. Now let's look at how to make our UIs interactive.
|
||||
|
||||
|
||||
## A Simple Example
|
||||
|
||||
```javascript
|
||||
@@ -35,33 +34,28 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Event Handling and Synthetic Events
|
||||
|
||||
With React you simply pass your event handler as a camelCased prop similar to how you'd do it in normal HTML. React ensures that all events behave identically in IE8 and above by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with [the W3C spec](http://www.w3.org/TR/DOM-Level-3-Events/), regardless of which browser you're using.
|
||||
|
||||
With React you simply pass your event handler as a camelCased prop similar to how you'd do it in normal HTML. React ensures that all events behave similarly in all browsers by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with [the W3C spec](http://www.w3.org/TR/DOM-Level-3-Events/), regardless of which browser you're using.
|
||||
|
||||
## Under the Hood: Autobinding and Event Delegation
|
||||
|
||||
Under the hood, React does a few things to keep your code performant and easy to understand.
|
||||
|
||||
**Autobinding:** When creating callbacks in JavaScript, you usually need to explicitly bind a method to its instance such that the value of `this` is correct. With React, every method is automatically bound to its component instance (except when using ES6 class syntax). React caches the bound method such that it's extremely CPU and memory efficient. It's also less typing!
|
||||
**Autobinding:** When creating callbacks in JavaScript, you usually need to explicitly bind a method to its instance such that the value of `this` is correct. With React, every method is automatically bound to its component instance ([except when using ES6 class syntax](/react/docs/reusable-components.html#no-autobinding)). React caches the bound method such that it's extremely CPU and memory efficient. It's also less typing!
|
||||
|
||||
**Event delegation:** React doesn't actually attach event handlers to the nodes themselves. When React starts up, it starts listening for all events at the top level using a single event listener. When a component is mounted or unmounted, the event handlers are simply added or removed from an internal mapping. When an event occurs, React knows how to dispatch it using this mapping. When there are no event handlers left in the mapping, React's event handlers are simple no-ops. To learn more about why this is fast, see [David Walsh's excellent blog post](http://davidwalsh.name/event-delegate).
|
||||
|
||||
|
||||
## Components are Just State Machines
|
||||
|
||||
React thinks of UIs as simple state machines. By thinking of a UI as being in various states and rendering those states, it's easy to keep your UI consistent.
|
||||
|
||||
In React, you simply update a component's state, and then render a new UI based on this new state. React takes care of updating the DOM for you in the most efficient way.
|
||||
|
||||
|
||||
## How State Works
|
||||
|
||||
A common way to inform React of a data change is by calling `setState(data, callback)`. This method merges `data` into `this.state` and re-renders the component. When the component finishes re-rendering, the optional `callback` is called. Most of the time you'll never need to provide a `callback` since React will take care of keeping your UI up-to-date for you.
|
||||
|
||||
|
||||
## What Components Should Have State?
|
||||
|
||||
Most of your components should simply take some data from `props` and render it. However, sometimes you need to respond to user input, a server request or the passage of time. For this you use state.
|
||||
@@ -70,15 +64,14 @@ Most of your components should simply take some data from `props` and render it.
|
||||
|
||||
A common pattern is to create several stateless components that just render data, and have a stateful component above them in the hierarchy that passes its state to its children via `props`. The stateful component encapsulates all of the interaction logic, while the stateless components take care of rendering data in a declarative way.
|
||||
|
||||
|
||||
## What *Should* Go in State?
|
||||
|
||||
**State should contain data that a component's event handlers may change to trigger a UI update.** In real apps this data tends to be very small and JSON-serializable. When building a stateful component, think about the minimal possible representation of its state, and only store those properties in `this.state`. Inside of `render()` simply compute any other information you need based on this state. You'll find that thinking about and writing applications in this way tends to lead to the most correct application, since adding redundant or computed values to state means that you need to explicitly keep them in sync rather than rely on React computing them for you.
|
||||
|
||||
## What *Shouldn’t* Go in State?
|
||||
## What *Shouldn't* Go in State?
|
||||
|
||||
`this.state` should only contain the minimal amount of data needed to represent your UI's state. As such, it should not contain:
|
||||
|
||||
* **Computed data:** Don't worry about precomputing values based on state — it's easier to ensure that your UI is consistent if you do all computation within `render()`. For example, if you have an array of list items in state and you want to render the count as a string, simply render `this.state.listItems.length + ' list items'` in your `render()` method rather than storing it on state.
|
||||
* **React components:** Build them in `render()` based on underlying props and state.
|
||||
* **Duplicated data from props:** Try to use props as the source of truth where possible. One valid use to store props in state is to be able to know its previous values, because props can change over time.
|
||||
* **Duplicated data from props:** Try to use props as the source of truth where possible. One valid use to store props in state is to be able to know its previous values, because props may change as the result of a parent component re-rendering.
|
||||
|
||||
@@ -8,7 +8,6 @@ next: multiple-components-zh-CN.html
|
||||
|
||||
我们已经学习如何使用 React [显示数据](/react/docs/displaying-data-zh-CN.html)。现在让我们来学习如何创建交互式界面。
|
||||
|
||||
|
||||
## 简单例子
|
||||
|
||||
```javascript
|
||||
@@ -35,7 +34,6 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 事件处理与合成事件(Synthetic Events)
|
||||
|
||||
React 里只需把事件处理器(event handler)以骆峰命名(camelCased)形式当作组件的 props 传入即可,就像使用普通 HTML 那样。React 内部创建一套合成事件系统来使所有事件在 IE8 和以上浏览器表现一致。也就是说,React 知道如何冒泡和捕获事件,而且你的事件处理器接收到的 events 参数与 [W3C 规范](http://www.w3.org/TR/DOM-Level-3-Events/) 一致,无论你使用哪种浏览器。
|
||||
@@ -48,19 +46,16 @@ React 里只需把事件处理器(event handler)以骆峰命名(camelCased
|
||||
|
||||
**事件代理 :** React 实际并没有把事件处理器绑定到节点本身。当 React 启动的时候,它在最外层使用唯一一个事件监听器处理所有事件。当组件被加载和卸载时,只是在内部映射里添加或删除事件处理器。当事件触发,React 根据映射来决定如何分发。当映射里处理器时,会当作空操作处理。参考 [David Walsh 很棒的文章](http://davidwalsh.name/event-delegate) 了解这样做高效的原因。
|
||||
|
||||
|
||||
## 组件其实是状态机(State Machines)
|
||||
|
||||
React 把用户界面当作简单状态机。把用户界面想像成拥有不同状态然后渲染这些状态,可以轻松让用户界面和数据保持一致。
|
||||
|
||||
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。React 来决定如何最高效地更新 DOM。
|
||||
|
||||
|
||||
## State 工作原理
|
||||
|
||||
常用的通知 React 数据变化的方法是调用 `setState(data, callback)`。这个方法会合并(merge) `data` 到 `this.state`,并重新渲染组件。渲染完成后,调用可选的 `callback` 回调。大部分情况下不需要提供 `callback`,因为 React 会负责把界面更新到最新状态。
|
||||
|
||||
|
||||
## 哪些组件应该有 State?
|
||||
|
||||
大部分组件的工作应该是从 `props` 里取数据并渲染出来。但是,有时需要对用户输入、服务器请求或者时间变化等作出响应,这时才需要使用 State。
|
||||
@@ -69,16 +64,14 @@ React 里,只需更新组件的 state,然后根据新的 state 重新渲染
|
||||
|
||||
常用的模式是创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 `props` 传给子级。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。
|
||||
|
||||
|
||||
## 哪些 *应该* 作为 State?
|
||||
|
||||
**State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。** 真实的应用中这种数据一般都很小且能被 JSON 序列化。当创建一个状态化的组件时,想象一下表示它的状态最少需要哪些数据,并只把这些数据存入 `this.state`。在 `render()` 里再根据 state 来计算你需要的其它数据。你会发现以这种方式思考和开发程序最终往往是正确的,因为如果在 state 里添加冗余数据或计算所得数据,需要你经常手动保持数据同步,不能让 React 来帮你处理。
|
||||
|
||||
|
||||
## 哪些 *不应该* 作为 State?
|
||||
|
||||
`this.state` 应该仅包括能表示用户界面状态所需的最少数据。因些,它不应该包括:
|
||||
|
||||
* **计算所得数据:** 不要担心根据 state 来预先计算数据 —— 把所有的计算都放到 `render()` 里更容易保证用户界面和数据的一致性。例如,在 state 里有一个数组(listItems),我们要把数组长度渲染成字符串, 直接在 `render()` 里使用 `this.state.listItems.length + ' list items'` 比把它放到 state 里好的多。
|
||||
* **React 组件:** 在 `render()` 里使用当前 props 和 state 来创建它。
|
||||
* **基于 props 的重复数据:** 尽可能使用 props 来作为惟一数据来源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为未来的 props 可能会变化。
|
||||
* **基于 props 的重复数据:** 尽可能使用 props 来作为实际状态的源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为 props 可能因为父组件重绘的结果而变化。
|
||||
|
||||
@@ -8,12 +8,10 @@ next: reusable-components-ko-KR.html
|
||||
|
||||
지금까지, 단일 컴포넌트에서 데이터를 표시하고 유저 입력을 다루는 것을 살펴보았습니다. 다음엔 React의 최고의 기능 중 하나인 조합가능성(composability)을 살펴봅시다.
|
||||
|
||||
|
||||
## 동기: 관심의 분리
|
||||
|
||||
명확히 정의된 인터페이스와 다른 컴포넌트를 재사용해 모듈러 컴포넌트를 구축하면, 함수와 클래스를 이용했을 때 얻을 수 있는 이점 대부분을 얻을 수 있습니다. 특히 앱에서 *다른 관심을 분리*할 수 있습니다.아무리 간단히 새 컴포넌트를 만들었다고 해도 말이죠. 당신의 애플리케이션에서 쓸 커스텀 컴포넌트 라이브러리를 만들어서, 당신의 도메인에 최적화된 방법으로 UI를 표현할 수 있게 됩니다.
|
||||
|
||||
|
||||
## 조합(Composition) 예제
|
||||
|
||||
간단히 페이스북 그래프 API를 사용해 프로필 사진과 유저이름을 보여주는 아바타 컴포넌트를 만든다고 합시다.
|
||||
@@ -54,14 +52,12 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 소유권(Ownership)
|
||||
|
||||
위의 예제에서, `Avatar` 인스턴스는 `ProfilePic`과 `ProfileLink`인스턴스를 *가지고* 있습니다. React에서 **소유자는 다른 컴포넌트의 `props`를 설정하는 컴포넌트입니다**. 더 정식으로 말하면, `X` 컴포넌트가 `Y` 컴포넌트의 `render()` 메소드 안에서 만들어졌다면, `Y`가 `X`를 *소유하고* 있다고 합니다. 앞에서 설명한 바와 같이, 컴포넌트는 자신의 `props`를 변경할 수 없습니다. `props`는 언제나 소유자가 설정한 것과 일치합니다. 이와 같은 중요한 성질은 UI가 일관성 있도록 해줍니다.
|
||||
위의 예제에서, `Avatar` 인스턴스는 `ProfilePic`과 `ProfileLink`인스턴스를 *가지고* 있습니다. React에서 **소유자는 다른 컴포넌트의 `props`를 설정하는 컴포넌트입니다**. 더 정식으로 말하면, `X` 컴포넌트가 `Y` 컴포넌트의 `render()` 메소드 안에서 만들어졌다면, `Y`가 `X`를 *소유하고* 있다고 합니다. 앞에서 설명한 바와 같이, 컴포넌트는 자신의 `props`를 변경할 수 없습니다. `props`는 언제나 소유자가 설정한 것과 일치합니다. 이와 같은 근본적인 불변성은 UI가 일관성 있도록 해줍니다.
|
||||
|
||||
소유(owner-ownee)관계와 부모·자식 관계를 구별하는 것은 중요합니다. 부모·자식 관계가 DOM에서부터 쓰던 익숙하고 이미 알고있던 단순한 것인 한편, 소유관계는 React 고유의 것입니다. 위의 예제에서, `Avatar`는 `div`, `ProfilePic`, `ProfileLink`인스턴스를 소유하고, `div`는 `ProfilePic`과 `ProfileLink`인스턴스의 (소유자가 아닌) **부모**입니다.
|
||||
|
||||
|
||||
## 자식
|
||||
|
||||
React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트나 JavaScript 표현식을 시작과 끝 태그 사이에 넣을 수 있습니다. 이렇게 말이죠.
|
||||
@@ -72,7 +68,6 @@ React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트
|
||||
|
||||
`Parent`는 `this.props.children`라는 특수 prop으로 자식들을 읽을 수 있습니다. **`this.props.children` 는 불투명한 데이터 구조이며,** [React.Children 유틸리티](/react/docs/top-level-api-ko-KR.html#react.children)를 사용해 자식들을 관리합니다.
|
||||
|
||||
|
||||
### 자식 Reconciliation (비교조정)
|
||||
|
||||
**Reconciliation은 React가 DOM을 각각 새로운 렌더 패스에 업데이트하는 과정입니다.** 일반적으로, 자식은 렌더하는 순서에 따라 비교조정됩니다. 예를 들어, 각각의 마크업을 생성하는 두 개의 렌더 패스가 있다고 해봅시다.
|
||||
@@ -91,7 +86,6 @@ React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트
|
||||
|
||||
직관적으로 보면, `<p>Paragraph 1</p>`가 없어졌습니다만 그러는 대신에, React는 첫 번째 자식의 텍스트를 비교조정하고 마지막 자식을 파괴하도록 DOM을 비교조정할 것입니다. React는 자식들의 *순서*에 따라 비교조정합니다.
|
||||
|
||||
|
||||
### 상태기반(Stateful) 자식
|
||||
|
||||
대부분의 컴포넌트에서는, 이것은 큰 문제가 아닙니다. 하지만 렌더 패스 간에 `this.state`를 유지하는 상태기반의 컴포넌트에서는 매우 문제가 될 수 있습니다.
|
||||
@@ -111,7 +105,6 @@ React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트
|
||||
</Card>
|
||||
```
|
||||
|
||||
|
||||
<a name="dynamic-children"></a>
|
||||
### 동적 자식
|
||||
|
||||
@@ -179,7 +172,6 @@ ReactFragment 객체를 넘기는 것으로 자식에 키를 할당할 수도
|
||||
|
||||
React에서 데이터는 위에서 말한 것처럼 `props`를 통해 소유자로부터 소유한 컴포넌트로 흐릅니다. 이것은 사실상 단방향 데이터 바인딩입니다. 소유자는 `props`나 `state`를 기준으로 계산한 어떤 값으로 소유한 컴포넌트의 props를 바인드합니다. 이 과정은 재귀적으로 발생하므로, 데이터의 변경은 자동으로 모든 곳에 반영됩니다.
|
||||
|
||||
|
||||
## 성능의 주의점
|
||||
|
||||
소유자가 가지고 있는 노드의 수가 많아지면 데이터가 변화하는 비용이 증가할 것으로 생각할 수도 있습니다. 좋은 소식은 JavaScript의 속도는 빠르고 `render()` 메소드는 꽤 간단한 경향이 있어, 대부분 애플리케이션에서 매우 빠르다는 점입니다. 덧붙여, 대부분의 병목 현상은 JS 실행이 아닌 DOM 변경에서 일어나고, React는 배치와 탐지 변경을 이용해 최적화해 줍니다.
|
||||
|
||||
@@ -8,59 +8,55 @@ next: reusable-components.html
|
||||
|
||||
So far, we've looked at how to write a single component to display data and handle user input. Next let's examine one of React's finest features: composability.
|
||||
|
||||
|
||||
## Motivation: Separation of Concerns
|
||||
|
||||
By building modular components that reuse other components with well-defined interfaces, you get much of the same benefits that you get by using functions or classes. Specifically you can *separate the different concerns* of your app however you please simply by building new components. By building a custom component library for your application, you are expressing your UI in a way that best fits your domain.
|
||||
|
||||
|
||||
## Composition Example
|
||||
|
||||
Let's create a simple Avatar component which shows a profile picture and username using the Facebook Graph API.
|
||||
Let's create a simple Avatar component which shows a Facebook page picture and name using the Facebook Graph API.
|
||||
|
||||
```javascript
|
||||
var Avatar = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ProfilePic username={this.props.username} />
|
||||
<ProfileLink username={this.props.username} />
|
||||
<PagePic pagename={this.props.pagename} />
|
||||
<PageLink pagename={this.props.pagename} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfilePic = React.createClass({
|
||||
var PagePic = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<img src={'https://graph.facebook.com/' + this.props.username + '/picture'} />
|
||||
<img src={'https://graph.facebook.com/' + this.props.pagename + '/picture'} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfileLink = React.createClass({
|
||||
var PageLink = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<a href={'https://www.facebook.com/' + this.props.username}>
|
||||
{this.props.username}
|
||||
<a href={'https://www.facebook.com/' + this.props.pagename}>
|
||||
{this.props.pagename}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<Avatar username="pwh" />,
|
||||
<Avatar pagename="Engineering" />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Ownership
|
||||
|
||||
In the above example, instances of `Avatar` *own* instances of `ProfilePic` and `ProfileLink`. In React, **an owner is the component that sets the `props` of other components**. More formally, if a component `X` is created in component `Y`'s `render()` method, it is said that `X` is *owned by* `Y`. As discussed earlier, a component cannot mutate its `props` — they are always consistent with what its owner sets them to. This fundamental invariant leads to UIs that are guaranteed to be consistent.
|
||||
|
||||
It's important to draw a distinction between the owner-ownee relationship and the parent-child relationship. The owner-ownee relationship is specific to React, while the parent-child relationship is simply the one you know and love from the DOM. In the example above, `Avatar` owns the `div`, `ProfilePic` and `ProfileLink` instances, and `div` is the **parent** (but not owner) of the `ProfilePic` and `ProfileLink` instances.
|
||||
In the above example, instances of `Avatar` *own* instances of `PagePic` and `PageLink`. In React, **an owner is the component that sets the `props` of other components**. More formally, if a component `X` is created in component `Y`'s `render()` method, it is said that `X` is *owned by* `Y`. As discussed earlier, a component cannot mutate its `props` — they are always consistent with what its owner sets them to. This fundamental invariant leads to UIs that are guaranteed to be consistent.
|
||||
|
||||
It's important to draw a distinction between the owner-ownee relationship and the parent-child relationship. The owner-ownee relationship is specific to React, while the parent-child relationship is simply the one you know and love from the DOM. In the example above, `Avatar` owns the `div`, `PagePic` and `PageLink` instances, and `div` is the **parent** (but not owner) of the `PagePic` and `PageLink` instances.
|
||||
|
||||
## Children
|
||||
|
||||
@@ -72,7 +68,6 @@ When you create a React component instance, you can include additional React com
|
||||
|
||||
`Parent` can read its children by accessing the special `this.props.children` prop. **`this.props.children` is an opaque data structure:** use the [React.Children utilities](/react/docs/top-level-api.html#react.children) to manipulate them.
|
||||
|
||||
|
||||
### Child Reconciliation
|
||||
|
||||
**Reconciliation is the process by which React updates the DOM with each new render pass.** In general, children are reconciled according to the order in which they are rendered. For example, suppose two render passes generate the following respective markup:
|
||||
@@ -91,7 +86,6 @@ When you create a React component instance, you can include additional React com
|
||||
|
||||
Intuitively, `<p>Paragraph 1</p>` was removed. Instead, React will reconcile the DOM by changing the text content of the first child and destroying the last child. React reconciles according to the *order* of the children.
|
||||
|
||||
|
||||
### Stateful Children
|
||||
|
||||
For most components, this is not a big deal. However, for stateful components that maintain data in `this.state` across render passes, this can be very problematic.
|
||||
@@ -111,7 +105,6 @@ In most cases, this can be sidestepped by hiding elements instead of destroying
|
||||
</Card>
|
||||
```
|
||||
|
||||
|
||||
### Dynamic Children
|
||||
|
||||
The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a `key`:
|
||||
@@ -178,7 +171,6 @@ You can also key children by passing a ReactFragment object. See [Keyed Fragment
|
||||
|
||||
In React, data flows from owner to owned component through `props` as discussed above. This is effectively one-way data binding: owners bind their owned component's props to some value the owner has computed based on its `props` or `state`. Since this process happens recursively, data changes are automatically reflected everywhere they are used.
|
||||
|
||||
|
||||
## A Note on Performance
|
||||
|
||||
You may be thinking that it's expensive to change data if there are a large number of nodes under an owner. The good news is that JavaScript is fast and `render()` methods tend to be quite simple, so in most applications this is extremely fast. Additionally, the bottleneck is almost always the DOM mutation and not JS execution. React will optimize this for you by using batching and change detection.
|
||||
|
||||
@@ -8,59 +8,55 @@ next: reusable-components-zh-CN.html
|
||||
|
||||
目前为止,我们已经学了如何用单个组件来展示数据和处理用户输入。下一步让我们来体验 React 最激动人心的特性之一:可组合性(composability)。
|
||||
|
||||
|
||||
## 动机:关注分离
|
||||
|
||||
通过复用那些接口定义良好的组件来开发新的模块化组件,我们得到了与使用函数和类相似的好处。具体来说就是能够通过开发简单的组件把程序的*不同关注面分离*。如果为程序开发一套自定义的组件库,那么就能以最适合业务场景的方式来展示你的用户界面。
|
||||
|
||||
## 组合实例
|
||||
|
||||
一起来使用 Facebook Graph API 开发显示个人图片和用户名的简单 Avatar 组件吧。
|
||||
让我们用 Facebook Graph API 来开发一个显示 Facebook 页面图片和用户名的简单 Avatar 组件吧。
|
||||
|
||||
```javascript
|
||||
var Avatar = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ProfilePic username={this.props.username} />
|
||||
<ProfileLink username={this.props.username} />
|
||||
<PagePic pagename={this.props.pagename} />
|
||||
<PageLink pagename={this.props.pagename} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfilePic = React.createClass({
|
||||
var PagePic = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<img src={'https://graph.facebook.com/' + this.props.username + '/picture'} />
|
||||
<img src={'https://graph.facebook.com/' + this.props.pagename + '/picture'} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfileLink = React.createClass({
|
||||
var PageLink = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<a href={'https://www.facebook.com/' + this.props.username}>
|
||||
{this.props.username}
|
||||
<a href={'https://www.facebook.com/' + this.props.pagename}>
|
||||
{this.props.pagename}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<Avatar username="pwh" />,
|
||||
<Avatar pagename="Engineering" />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 从属关系
|
||||
|
||||
上面例子中,`Avatar` 拥有 `ProfilePic` 和 `ProfileLink` 的实例。`拥有者` 就是给其它组件设置 `props` 的那个组件。更正式地说,
|
||||
如果组件 `Y` 在 `render()` 方法是创建了组件 `X`,那么 `Y` 就拥有 `X`。上面讲过,组件不能修改自身的 `props` - 它们总是与它们拥有者设置的保持一致。这是保持用户界面一致性的基本不变量。
|
||||
|
||||
把从属关系与父子关系加以区别至关重要。从属关系是 React 特有的,而父子关系简单来讲就是DOM 里的标签的关系。在上一个例子中,`Avatar` 拥有 `div`、`ProfilePic` 和 `ProfileLink` 实例,`div` 是 `ProfilePic` 和 `ProfileLink` 实例的**父级**(但不是拥有者)。
|
||||
上面例子中,`Avatar` 拥有 `PagePic` 和 `PageLink` 的实例。`拥有者` 就是给其它组件设置 `props` 的那个组件。更正式地说,如果组件 `Y` 在 `render()` 方法是创建了组件 `X`,那么 `Y` 就拥有 `X`。上面讲过,组件不能修改自身的 `props` - 它们总是与它们拥有者设置的保持一致。这是保持用户界面一致性的基本不变量。
|
||||
|
||||
把从属关系与父子关系加以区别至关重要。从属关系是 React 特有的,而父子关系简单来讲就是DOM 里的标签的关系。在上一个例子中,`Avatar` 拥有 `div`、`PagePic` 和 `PageLink` 实例,`div` 是 `PagePic` 和 `PageLink` 实例的**父级**(但不是拥有者)。
|
||||
|
||||
## 子级
|
||||
|
||||
@@ -168,7 +164,7 @@ var MyComponent = React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
也可以传递ReactFragment 对象 来做有 key 的子级。详见[Keyed Fragments](create-fragment.html)
|
||||
也可以传递ReactFragment 对象 来做有 key 的子级。详见[Keyed Fragments](create-fragment.html)
|
||||
|
||||
## 数据流
|
||||
|
||||
@@ -182,5 +178,5 @@ React 里,数据通过上面介绍过的 `props` 从拥有者流向归属者
|
||||
但是,有时候需要做细粒度的性能控制。这种情况下,可以重写 `shouldComponentUpdate()` 方法返回 false 来让 React 跳过对子树的处理。参考 [React reference docs](/react/docs/component-specs.html) 了解更多。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> 如果在数据变化时让 `shouldComponentUpdate()` 返回 false,React 就不能保证用户界面同步。当使用它的时候一定确保你清楚到底做了什么,并且只在遇到明显性能问题的时候才使用它。不要低估 JavaScript 的速度,DOM 操作通常才是慢的原因。
|
||||
|
||||
@@ -249,7 +249,7 @@ ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
Oppure usando la nuova sintassi freccia di ES6:
|
||||
|
||||
```javascript
|
||||
var HelloMessage = (props) => <div>Ciao {props.name}</div>;
|
||||
const HelloMessage = (props) => <div>Ciao {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
|
||||
@@ -227,4 +227,4 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
|
||||
### ミックスインはありません
|
||||
|
||||
不幸なことに、ES6はミックスインのサポートを行いません。それゆえ、ReactをES6のクラスと一緒に使う際にはミックスインのサポートはありません。代わりに、ミックスインに頼ることなくそれらのユースケースをサポートするのが簡単になるよう努力しています。
|
||||
不幸なことに、ES6はミックスインのサポートを行いません。それゆえ、ReactをES6のクラスと一緒に使う際にはミックスインのサポートはありません。代わりに、ミックスインに頼ることなくそれらのユースケースをサポートするのが簡単になるよう努力しています。
|
||||
|
||||
@@ -8,7 +8,6 @@ next: transferring-props-ko-KR.html
|
||||
|
||||
인터페이스를 설계할 때, 공통적으로 사용되는 디자인 요소들(버튼, 폼 필드, 레이아웃 컴포넌트 등.)을 잘 정의된 인터페이스의 재사용 가능한 컴포넌트로 분해합니다. 이런 방법으로 다음에 UI를 구축할 때에는 훨씬 적은 코드로 만들 수 있습니다. 이 말은 더 빠른 개발 시간, 더 적은 버그, 더 적은 용량으로 할 수 있다는 뜻이죠.
|
||||
|
||||
|
||||
## Prop 검증
|
||||
|
||||
앱의 규모가 커지면 컴포넌트들이 바르게 사용되었는지 확인하는게 도움이 됩니다. 확인은 `propTypes`를 명시해서 할 수 있습니다. `React.PropTypes`는 받은 데이터가 적절한지(valid) 확인하는데 사용할 수 있는 다양한 검증자(validator)를 제공합니다. prop에 부적절한 값을 명시한다면 JavaScript 콘솔에 경고가 보일 것입니다. 성능상의 문제로 `propTypes`는 개발 모드에서만 검사됩니다. 다음은 제공되는 검증자를 설명하는 예제입니다.
|
||||
@@ -78,7 +77,6 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## 기본 Prop 값
|
||||
|
||||
React는 매우 선언적(declarative)인 방법으로 `props`의 기본값을 정의할 수 있게 해줍니다.
|
||||
@@ -230,3 +228,30 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
### 믹스인 안됨
|
||||
|
||||
불행하게도 ES6는 믹스인에 대한 지원이 없이 출시되었기 때문에, React에서 ES6 클래스를 사용한다면 믹스인을 사용할 방법이 없습니다. 대신, 우리는 믹스인에 의존하지 않고도 동작하도록 만들기 위해 열심히 노력하고 있습니다.
|
||||
|
||||
<a name="stateless-functions"></a>
|
||||
## 상태를 가지지 않는 함수
|
||||
|
||||
React 클래스를 일반 JavaScript 함수로 작성할 수도 있습니다. 상태를 가지지 않는 함수 문법을 사용하는 예제입니다.
|
||||
|
||||
```javascript
|
||||
function HelloMessage(props) {
|
||||
return <div>Hello {props.name}</div>;
|
||||
}
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
아니면 ES6의 화살표 문법을 사용할 수 있습니다.
|
||||
|
||||
```javascript
|
||||
const HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
이 단순화된 컴포넌트 API는 prop의 순수 함수인 컴포넌트를 나타냅니다. 이 컴포넌트는 내부 상태가 없어야 하고, 내부 인스턴스가 없어야 하고, 컴포넌트 생명주기 메소드가 없어야 합니다. 아무런 준비 과정없이 입력에 대한 순수한 기능적 변환이어야 합니다.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 상태를 가지지 않는 함수는 내부 인스턴스가 없기 때문에, ref를 상태를 가지지않는 함수에 넣을 수 없습니다. 상태를 가지지 않는 함수는 명령형(imperative) API를 제공하지 않기 때문에 일반적으로 이것은 문제가 되지 않습니다. 명령형 API없이 인스턴스에 할 수 있는 것이 많지 않기도 하죠. 하지만 상태를 가지지 않는 컴포넌트의 DOM 노드를 검색하길 원한다면, 반드시 상태 기반 컴포넌트(예. ES6 클래스 컴포넌트)로 컴포넌트를 감싸고 상태 기반 래퍼 컴포넌트에 ref를 붙여야 합니다.
|
||||
|
||||
이상적으로는, 대부분의 컴포넌트는 상태를 가지지 않는 함수여야 합니다. 왜냐 하면 이런 상태를 가지지 않는 컴포넌트는 React 코어 안에서 더 빠른 코드 경로를 거치기 때문입니다. 이는 가능한 한 추천하는 패턴입니다.
|
||||
|
||||
@@ -8,7 +8,6 @@ next: transferring-props.html
|
||||
|
||||
When designing interfaces, break down the common design elements (buttons, form fields, layout components, etc.) into reusable components with well-defined interfaces. That way, the next time you need to build some UI, you can write much less code. This means faster development time, fewer bugs, and fewer bytes down the wire.
|
||||
|
||||
|
||||
## Prop Validation
|
||||
|
||||
As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify `propTypes`. `React.PropTypes` exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. Note that for performance reasons `propTypes` is only checked in development mode. Here is an example documenting the different validators provided:
|
||||
@@ -79,6 +78,26 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
### Single Child
|
||||
|
||||
With `React.PropTypes.element` you can specify that only a single child can be passed to a component as children.
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // This must be exactly one element or it will warn.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
## Default Prop Values
|
||||
|
||||
@@ -97,10 +116,9 @@ var ComponentWithDefaultProps = React.createClass({
|
||||
|
||||
The result of `getDefaultProps()` will be cached and used to ensure that `this.props.value` will have a value if it was not specified by the parent component. This allows you to safely just use your props without having to write repetitive and fragile code to handle that yourself.
|
||||
|
||||
|
||||
## Transferring Props: A Shortcut
|
||||
|
||||
A common type of React component is one that extends a basic HTML element in a simple way. Often you'll want to copy any HTML attributes passed to your component to the underlying HTML element to save typing. You can use the JSX _spread_ syntax to achieve this:
|
||||
A common type of React component is one that extends a basic HTML element in a simple way. Often you'll want to copy any HTML attributes passed to your component to the underlying HTML element. To save typing, you can use the JSX _spread_ syntax to achieve this:
|
||||
|
||||
```javascript
|
||||
var CheckLink = React.createClass({
|
||||
@@ -118,28 +136,6 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
## Single Child
|
||||
|
||||
With `React.PropTypes.element` you can specify that only a single child can be passed to
|
||||
a component as children.
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // This must be exactly one element or it will throw.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
## Mixins
|
||||
|
||||
Components are the best way to reuse code in React, but sometimes very different components may share some common functionality. These are sometimes called [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). React provides `mixins` to solve this problem.
|
||||
@@ -209,13 +205,14 @@ export class Counter extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {count: props.initialCount};
|
||||
this.tick = this.tick.bind(this);
|
||||
}
|
||||
tick() {
|
||||
this.setState({count: this.state.count + 1});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div onClick={this.tick.bind(this)}>
|
||||
<div onClick={this.tick}>
|
||||
Clicks: {this.state.count}
|
||||
</div>
|
||||
);
|
||||
@@ -227,14 +224,39 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
|
||||
### No Autobinding
|
||||
|
||||
Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` or [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `=>`.
|
||||
Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` or [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `=>`:
|
||||
|
||||
```javascript
|
||||
// You can use bind() to preserve `this`
|
||||
<div onClick={this.tick.bind(this)}>
|
||||
|
||||
// Or you can use arrow functions
|
||||
<div onClick={() => this.tick()}>
|
||||
```
|
||||
|
||||
We recommend that you bind your event handlers in the constructor so they are only bound once for every instance:
|
||||
|
||||
```javascript
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {count: props.initialCount};
|
||||
this.tick = this.tick.bind(this);
|
||||
}
|
||||
```
|
||||
|
||||
Now you can use `this.tick` directly as it was bound once in the constructor:
|
||||
|
||||
```javascript
|
||||
// It is already bound in the constructor
|
||||
<div onClick={this.tick}>
|
||||
```
|
||||
|
||||
This is better for performance of your application, especially if you implement [shouldComponentUpdate()](/react/docs/component-specs.html#updating-shouldcomponentupdate) with a [shallow comparison](/react/docs/shallow-compare.html) in the child components.
|
||||
|
||||
### No Mixins
|
||||
|
||||
Unfortunately ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes. Instead, we're working on making it easier to support such use cases without resorting to mixins.
|
||||
|
||||
|
||||
|
||||
## Stateless Functions
|
||||
|
||||
You may also define your React classes as a plain JavaScript function. For example using the stateless function syntax:
|
||||
@@ -249,16 +271,15 @@ ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
Or using the new ES6 arrow syntax:
|
||||
|
||||
```javascript
|
||||
var HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
const HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
|
||||
This simplified component API is intended for components that are pure functions of their props. These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate.
|
||||
However, you may still specify `.propTypes` and `.defaultProps` by setting them as properties on the function, just as you would set them on an ES6 class.
|
||||
|
||||
> NOTE:
|
||||
>
|
||||
>
|
||||
> Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component. Normally this isn't an issue, since stateless functions do not provide an imperative API. Without an imperative API, there isn't much you could do with an instance anyway. However, if a user wants to find the DOM node of a stateless function component, they must wrap the component in a stateful component (eg. ES6 class component) and attach the ref to the stateful wrapper component.
|
||||
|
||||
In an ideal world, most of your components would be stateless functions because these stateless components can follow a faster code path within the React core. This is the recommended pattern, when possible.
|
||||
|
||||
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.
|
||||
|
||||
@@ -8,7 +8,6 @@ next: transferring-props-zh-CN.html
|
||||
|
||||
设计接口的时候,把通用的设计元素(按钮,表单框,布局组件等)拆成接口良好定义的可复用的组件。这样,下次开发相同界面程序时就可以写更少的代码,也意义着更高的开发效率,更少的 Bug 和更少的程序体积。
|
||||
|
||||
|
||||
## Prop 验证
|
||||
|
||||
随着应用不断变大,保证组件被正确使用变得非常有用。为此我们引入 `propTypes`。`React.PropTypes` 提供很多验证器 (validator) 来验证传入数据的有效性。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。注意为了性能考虑,只在开发环境验证 `propTypes`。下面用例子来说明不同验证器的区别:
|
||||
@@ -32,10 +31,12 @@ React.createClass({
|
||||
// React 元素
|
||||
optionalElement: React.PropTypes.element,
|
||||
|
||||
// 你同样可以断言一个 prop 是一个类的实例。
|
||||
// 用 JS 的 instanceof 操作符声明 prop 为类的实例。
|
||||
optionalMessage: React.PropTypes.instanceOf(Message),
|
||||
|
||||
// 用 enum 来限制 prop 只接受指定的值。
|
||||
// 你可以用 enum 的方式
|
||||
// 确保你的 prop 被限定为指定值。
|
||||
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
|
||||
|
||||
// 指定的多个对象类型中的一个
|
||||
@@ -57,14 +58,16 @@ React.createClass({
|
||||
fontSize: React.PropTypes.number
|
||||
}),
|
||||
|
||||
// 以后任意类型加上 `isRequired` 来使 prop 不可空。
|
||||
// 你可以在任意东西后面加上 `isRequired`
|
||||
// 来确保 如果 prop 没有提供 就会显示一个警告。
|
||||
requiredFunc: React.PropTypes.func.isRequired,
|
||||
|
||||
// 不可空的任意类型
|
||||
requiredAny: React.PropTypes.any.isRequired,
|
||||
|
||||
// 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接
|
||||
// 使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
|
||||
// 你可以自定义一个验证器。如果验证失败需要返回一个 Error 对象。
|
||||
// 不要直接使用 `console.warn` 或抛异常,
|
||||
// 因为这在 `oneOfType` 里不起作用。
|
||||
customProp: function(props, propName, componentName) {
|
||||
if (!/matchme/.test(props[propName])) {
|
||||
return new Error('Validation failed!');
|
||||
@@ -75,6 +78,26 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
### Single Child
|
||||
|
||||
用 `React.PropTypes.element` 你可以指定仅有一个子级能被传送给组件
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // 这里必须是一个元素否则就会警告
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
## 默认 Prop 值
|
||||
|
||||
@@ -93,9 +116,9 @@ var ComponentWithDefaultProps = React.createClass({
|
||||
|
||||
当父级没有传入 props 时,`getDefaultProps()` 可以保证 `this.props.value` 有默认值,注意 `getDefaultProps` 的结果会被 *缓存*。得益于此,你可以直接使用 props,而不必写手动编写一些重复或无意义的代码。
|
||||
|
||||
## 传递 Props:小技巧
|
||||
## 传递 Props:捷径
|
||||
|
||||
有一些常用的 React 组件只是对 HTML 做简单扩展。通常,你想少写点代码来把传入组件的 props 复制到对应的 HTML 元素上。这时 JSX 的 _spread_ 语法会帮到你:
|
||||
有一些常用的 React 组件只是对 HTML 做简单扩展。通常,你想 复制任何传进你的组件的HTML属性 到底层的HTML元素上。为了减少输入,你可以用 JSX _spread_ 语法来完成:
|
||||
|
||||
```javascript
|
||||
var CheckLink = React.createClass({
|
||||
@@ -113,28 +136,6 @@ ReactDOM.render(
|
||||
);
|
||||
```
|
||||
|
||||
## 单个子级
|
||||
|
||||
`React.PropTypes.element` 可以限定只能有一个子级传入。
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // 有且仅有一个元素,否则会抛异常。
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Mixins
|
||||
|
||||
组件是 React 里复用代码最佳方式,但是有时一些复杂的组件间也需要共用一些功能。有时会被称为 [跨切面关注点](https://en.wikipedia.org/wiki/Cross-cutting_concern)。React 使用 `mixins` 来解决这类问题。
|
||||
@@ -228,3 +229,29 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
|
||||
不幸的是ES6的发布没有任何mixin的支持。因此,当你在ES6 classes下使用React时不支持mixins。作为替代,我们正在努力使它更容易支持这些用例不依靠mixins。
|
||||
|
||||
## 无状态函数
|
||||
|
||||
你也可以用 JavaScript 函数来定义你的 React 类。例如使用无状态函数语法:
|
||||
|
||||
```javascript
|
||||
function HelloMessage(props) {
|
||||
return <div>Hello {props.name}</div>;
|
||||
}
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
或者使用新的ES6箭头函数:
|
||||
|
||||
```javascript
|
||||
const HelloMessage = (props) => <div>Hello {props.name}</div>;
|
||||
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
|
||||
```
|
||||
|
||||
这个简化的组件API旨在用于那些纯函数态的组件 。这些组件必须没有保持任何内部状态,没有备份实例,也没有组件生命周期方法。他们纯粹的函数式的转化他们的输入,没有引用。
|
||||
然而,你仍然可以以设置为函数的properties的方式来指定 `.propTypes` 和 `.defaultProps`,就像你在ES6类里设置他们那样。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 因为无状态函数没有备份实例,你不能附加一个引用到一个无状态函数组件。 通常这不是问题,因为无状态函数不提供一个命令式的API。没有命令式的API,你就没有任何需要实例来做的事。然而,如果用户想查找无状态函数组件的DOM节点,他们必须把这个组件包装在一个有状态组件里(比如,ES6 类组件) 并且连接一个引用到有状态的包装组件。
|
||||
|
||||
在理想世界里,你的大多数组件都应该是无状态函数,因为将来我们可能会用避免不必要的检查和内存分配的方式来对这些组件进行优化。 如果可能,这是推荐的模式。
|
||||
|
||||
@@ -27,16 +27,14 @@ Nel resto di questo tutorial vengono illustrate le best practices, usando JSX e
|
||||
Nella maggior parte dei casi dovresti esplicitamente passare le proprietà. Ciò assicura che venga esposto soltanto un sottoinsieme dell'API interna, del cui funzionamento si è certi.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Ciao mondo!
|
||||
@@ -58,22 +56,20 @@ A volte passare manualmente ciascuna proprietà può essere noioso e fragile. In
|
||||
Elenca tutte le proprietà che desideri consumare, seguite da `...other`.
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
Ciò assicura che vengano passate tutte le proprietà TRANNE quelle che stai consumando tu stesso.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` contiene { onClick: console.log } ma non la proprietà checked
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` contiene { onClick: console.log } ma non la proprietà checked
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Ciao mondo!
|
||||
@@ -89,15 +85,13 @@ ReactDOM.render(
|
||||
Usa sempre il pattern di destrutturazione quando trasferisci altre proprietà sconosciute in `other`.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// ANTI-PATTERN: `checked` sarebbe passato al componente interno
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// ANTI-PATTERN: `checked` sarebbe passato al componente interno
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Consumare e Trasferire la Stessa Proprietà
|
||||
@@ -105,23 +99,21 @@ var FancyCheckbox = React.createClass({
|
||||
Se il tuo componente desidera consumare una proprietà, ma anche passarla ad altri, puoi passarla esplicitamente mediante `checked={checked}`. Questo è preferibile a passare l'intero oggetto `this.props` dal momento che è più facile effettuarne il linting e il refactoring.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> NOTA:
|
||||
@@ -150,14 +142,12 @@ z; // { a: 3, b: 4 }
|
||||
Se non usi JSX, puoi usare una libreria per ottenere il medesimo pattern. Underscore supporta `_.omit` per omettere delle proprietà ed `_.extend` per copiare le proprietà in un nuovo oggetto.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -29,16 +29,14 @@ React.createElement(Component, Object.assign({}, this.props, { more: 'values' })
|
||||
ほとんどの場合、プロパティを明確に子要素に渡すべきです。それは、内部のAPIのサブセットだけを外に出していることと、認識しているプロパティが動作することを保証します。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -59,22 +57,20 @@ ReactDOM.render(
|
||||
以下のように `...other` を使うことで、使いたいプロパティを一覧にすることができます。
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
これは、自分で指定したものは 除き 、全てのpropsを渡すことを保証します。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` は { onClick: console.log } を含みますが、 checked プロパティは含みません。
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` は { onClick: console.log } を含みますが、 checked プロパティは含みません。
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -89,15 +85,13 @@ ReactDOM.render(
|
||||
未知の `other` propsを移譲する際には、分割代入パターンを常に使ってください。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// アンチパターン: `checked` が内部のコンポーネントに渡されます。
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// アンチパターン: `checked` が内部のコンポーネントに渡されます。
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 同じpropを使い、移譲する
|
||||
@@ -105,23 +99,21 @@ var FancyCheckbox = React.createClass({
|
||||
コンポーネントがプロパティを使うだけでなく、子要素に渡したい場合は、明確に `checked={checked}` と記述することで再度渡すことができます。 `this.props` オブジェクトで全てを渡すほうが、リファクタリングやチェックをしやすいので好ましいです。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> 注意:
|
||||
@@ -148,14 +140,12 @@ z; // { a: 3, b: 4 }
|
||||
JSXを使わない際には、同じパターンを行うライブラリを使うことができます。Underscoreでは、 `_.omit` を使ってプロパティをフィルタしたり、 `_.extend` を使って新しいオブジェクトにプロパティをコピーしたりできます。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -27,16 +27,14 @@ React.createElement(Component, Object.assign({}, this.props, { more: 'values' })
|
||||
대부분의 경우 명시적으로 프로퍼티를 아래로 전달해야 합니다. 이는 동작을 확신하는 내부 API의 일부만 공개하도록 합니다.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
세상아 안녕!
|
||||
@@ -50,30 +48,29 @@ ReactDOM.render(
|
||||
## JSX에서 `...`를 사용해 전달하기
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 아래의 예제에서는 실험적인 ES7 문법이 사용되었기 때문에 `--harmony ` 플래그가 필요합니다. 브라우저에서 JSX 변환기를 사용 중이라면, `<script type="text/jsx;harmony=true">`를 사용해 스크립트를 작성하세요. 자세히 알아보려면 아래의 [잔여 프로퍼티와 스프레드 프로퍼티 ...](/react/docs/transferring-props-ko-KR.html#rest-and-spread-properties-...)를 확인하세요.
|
||||
>
|
||||
> `...` 구문은 객체 잔여 스프레드 제안의 일부입니다. 이 제안은 표준화 과정에 있습니다. 더 자세한 내용은 밑의 [잔여 프로퍼티와 스프레드 프로퍼티 ...](/react/docs/transferring-props.html#rest-and-spread-properties-...) 부분을 참고하세요.
|
||||
|
||||
|
||||
때로는 모든 프로퍼티를 일일이 전달 하는것은 지루하고 덧없는 작업입니다. 이 경우 [구조 해체 할당(destructuring assignment)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)을 다른 프로퍼티를 함께 사용해 미상의 프로퍼티를 추출할 수 있습니다.
|
||||
|
||||
소비할 프로퍼티들을 나열하고, 그 뒤에 `...other`를 넣습니다.
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
이는 지금 소비한 props를 *제외한* 나머지를 아래로 전달합니다.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other`에는 { onClick: console.log }가 포함되지만 checked 프로퍼티는 제외됩니다
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other`에는 { onClick: console.log }가 포함되지만 checked 프로퍼티는 제외됩니다
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
세상아 안녕!
|
||||
@@ -89,15 +86,13 @@ ReactDOM.render(
|
||||
미상의 `other` props을 전달할 때는 항상 구조 해체 패턴을 사용하세요.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// 반례: `checked` 또한 내부 컴포넌트로 전달될 것입니다
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// 반례: `checked` 또한 내부 컴포넌트로 전달될 것입니다
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 같은 Prop을 소비하고 전달하기
|
||||
@@ -105,23 +100,21 @@ var FancyCheckbox = React.createClass({
|
||||
컴포넌트가 프로퍼티를 사용하지만 계속 넘기길 원한다면, `checked={checked}`처럼 명시적으로 다시 넘길 수 있습니다. 리팩토링과 린트(lint)하기가 더 쉬우므로 이 방식이 `this.props` 객체 전부를 넘기는 것보다 낫습니다.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> 주의:
|
||||
@@ -133,7 +126,7 @@ var FancyCheckbox = React.createClass({
|
||||
|
||||
잔여(Rest, `...`) 프로퍼티는 객체에서 소비되지 않은 나머지 프로퍼티를 추출해 새로운 객체로 만들 수 있게 해 줍니다. 구조 해체 패턴에서 열거된 다른 프로퍼티들은 모두 제외됩니다.
|
||||
|
||||
이는 [ES7 제안](https://github.com/sebmarkbage/ecmascript-rest-spread)의 실험적인 구현체입니다.
|
||||
이 제안은 2 단계에 돌입해 이제 바벨에서 기본값으로 활성화되어있습니다. 바벨의 이전 버전은 `babel --optional es7.objectRestSpread`로 명시적으로 활성화 할 필요가 있을 수도 있습니다.
|
||||
|
||||
```javascript
|
||||
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
|
||||
@@ -151,14 +144,12 @@ z; // { a: 3, b: 4 }
|
||||
JSX를 사용하지 않는다면 라이브러리를 사용해 같은 패턴을 쓸 수 있습니다. Underscore에서는 `_.omit`을 사용해 특정 프로퍼티를 제외하거나 `_.extend`를 사용해 새로운 객체로 프로퍼티를 복사할 수 있습니다.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -20,23 +20,21 @@ If you don't use JSX, you can use any object helper such as ES6 `Object.assign`
|
||||
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
|
||||
```
|
||||
|
||||
The rest of this tutorial explains best practices. It uses JSX and experimental ES7 syntax.
|
||||
The rest of this tutorial explains best practices. It uses JSX and experimental ECMAScript syntax.
|
||||
|
||||
## Manual Transfer
|
||||
|
||||
Most of the time you should explicitly pass the properties down. This ensures that you only expose a subset of the inner API, one that you know will work.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -58,22 +56,20 @@ Sometimes it's fragile and tedious to pass every property along. In that case yo
|
||||
List out all the properties that you would like to consume, followed by `...other`.
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
This ensures that you pass down all the props EXCEPT the ones you're consuming yourself.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` contains { onClick: console.log } but not the checked property
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` contains { onClick: console.log } but not the checked property
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -89,39 +85,35 @@ ReactDOM.render(
|
||||
Always use the destructuring pattern when transferring unknown `other` props.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// ANTI-PATTERN: `checked` would be passed down to the inner component
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// ANTI-PATTERN: `checked` would be passed down to the inner component
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Consuming and Transferring the Same Prop
|
||||
|
||||
If your component wants to consume a property but also wants to pass it along, you can repass it explicitly with `checked={checked}`. This is preferable to passing the full `this.props` object since it's easier to refactor and lint.
|
||||
If your component wants to consume a property but also wants to pass it along, you can repass it explicitly with `checked={checked}`. This is preferable to passing the full `props` object since it's easier to refactor and lint.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> NOTE:
|
||||
@@ -132,7 +124,7 @@ var FancyCheckbox = React.createClass({
|
||||
|
||||
Rest properties allow you to extract the remaining properties from an object into a new object. It excludes every other property listed in the destructuring pattern.
|
||||
|
||||
This is an experimental implementation of an [ES7 proposal](https://github.com/sebmarkbage/ecmascript-rest-spread).
|
||||
This is an experimental implementation of an [ECMAScript proposal](https://github.com/sebmarkbage/ecmascript-rest-spread).
|
||||
|
||||
```javascript
|
||||
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
|
||||
@@ -143,21 +135,19 @@ z; // { a: 3, b: 4 }
|
||||
|
||||
> Note:
|
||||
>
|
||||
> This proposal has reached stage 2 and is now enabled by default in Babel. Older versions of Babel may need to explicitly enable this transform with `babel --optional es7.objectRestSpread`
|
||||
> To transform rest and spread properties using Babel 6, you need to install the [`es2015`](https://babeljs.io/docs/plugins/preset-es2015/) preset, the [`transform-object-rest-spread`](https://babeljs.io/docs/plugins/transform-object-rest-spread/) plugin and configure them in the `.babelrc` file.
|
||||
|
||||
## Transferring with Underscore
|
||||
|
||||
If you don't use JSX, you can use a library to achieve the same pattern. Underscore supports `_.omit` to filter out properties and `_.extend` to copy properties onto a new object.
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -20,23 +20,21 @@ React 里有一个非常常用的模式就是对组件做一层抽象。组件
|
||||
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
|
||||
```
|
||||
|
||||
下面的教程介绍一些最佳实践。使用了 JSX 和 ES7 的还在试验阶段的特性。
|
||||
下面的教程介绍一些最佳实践。使用了 JSX 和 试验性的ECMAScript 语法。
|
||||
|
||||
## 手动传递
|
||||
|
||||
大部分情况下你应该显式地向下传递 props。这样可以确保只公开你认为是安全的内部 API 的子集。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -58,22 +56,20 @@ ReactDOM.render(
|
||||
列出所有要当前使用的属性,后面跟着 `...other`。
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
var { checked, ...other } = props;
|
||||
```
|
||||
|
||||
这样能确保把所有 props 传下去,*除了* 那些已经被使用了的。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` 包含 { onClick: console.log } 但 checked 属性除外
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` 包含 { onClick: console.log } 但 checked 属性除外
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
ReactDOM.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
@@ -83,58 +79,52 @@ ReactDOM.render(
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> 上面例子中,`checked` 属性也是一个有效的 DOM 属性。如果你没有使用解构赋值,那么可能无意中把它传下去。
|
||||
|
||||
在传递这些未知的 `other` 属性时,要经常使用解构赋值模式。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// 反模式:`checked` 会被传到里面的组件里
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var fancyClass = props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// 反模式:`checked` 会被传到里面的组件里
|
||||
return (
|
||||
<div {...props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 使用和传递同一个 Prop
|
||||
|
||||
如果组件需要使用一个属性又要往下传递,可以直接使用 `checked={checked}` 再传一次。这样做比传整个 `this.props` 对象要好,因为更利于重构和语法检查。
|
||||
如果组件需要使用一个属性又要往下传递,可以直接使用 `checked={checked}` 再传一次。这样做比传整个 `props` 对象要好,因为更利于重构和语法检查。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var { checked, title, ...other } = props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>
|
||||
> 顺序很重要,把 `{...other}` 放到 JSX props 前面会使它不被覆盖。上面例子中我们可以保证 input 的 type 是 `"checkbox"`。
|
||||
|
||||
|
||||
## 剩余属性和展开属性 `...`
|
||||
|
||||
剩余属性可以把对象剩下的属性提取到一个新的对象。会把所有在解构赋值中列出的属性剔除。
|
||||
|
||||
这是 [ES7 草案](https://github.com/sebmarkbage/ecmascript-rest-spread) 中的试验特性。
|
||||
这是 [ECMAScript 草案](https://github.com/sebmarkbage/ecmascript-rest-spread) 中的试验特性。
|
||||
|
||||
```javascript
|
||||
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
|
||||
@@ -145,22 +135,19 @@ z; // { a: 3, b: 4 }
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 使用 [JSX 命令行工具](https://www.npmjs.com/package/react-tools) 配合 `--harmony` 标记来启用 ES7 语法。
|
||||
|
||||
> 要用 Babel 6转换 rest 和 spread 属性,你需要安装 [`es2015`](https://babeljs.io/docs/plugins/preset-es2015/) preset,[`transform-object-rest-spread`](https://babeljs.io/docs/plugins/transform-object-rest-spread/) 插件并在 `.babelrc` 里配置他们.
|
||||
|
||||
## 使用 Underscore 来传递
|
||||
|
||||
如果不使用 JSX,可以使用一些库来实现相同效果。Underscore 提供 `_.omit` 来过滤属性,`_.extend` 复制属性到新的对象。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
function FancyCheckbox(props) {
|
||||
var checked = props.checked;
|
||||
var other = _.omit(props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -68,6 +68,9 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
|
||||
이것은 사용자 입력을 받아들이지만, 시작에서부터 140자로 값을 자릅니다.
|
||||
|
||||
### 체크박스와 라디오 버튼의 잠제적인 문제
|
||||
|
||||
변경 핸들링을 일반화하기 위해 React는 `change` 이벤트 대신에 `click` 이벤트를 사용하는 것에 주의하세요. `change` 핸들러 안에서 `preventDefault`를 호출하는 경우를 재외하고 이 동작은 예상대로 동작합니다. 이런 경우 `preventDefault`를 제거하거나, `setTimeout`에 `checked`의 전환을 넣어서 해결 가능합니다.
|
||||
|
||||
## 제어되지 않는(Uncontrolled) 컴포넌트
|
||||
|
||||
@@ -91,7 +94,7 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
}
|
||||
```
|
||||
|
||||
이 예제는 위에있는 **제어되는 컴포넌트**에 더 가깝게 동작할 것입니다.
|
||||
이 예제는 위에있는 **제어되지 않는 컴포넌트**에 더 가깝게 동작할 것입니다.
|
||||
|
||||
마찬가지로, `<input>`은 `defaultChecked`를 지원하고 `<select>`는 `defaultValue`를 지원합니다.
|
||||
|
||||
@@ -99,10 +102,8 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
>
|
||||
> `defaultValue`, `defaultChecked` prop은 최초 렌더에서만 사용됩니다. 뒤에 일어나는 렌더에서 값을 업데이트할 필요가 있다면, [제어되는(controlled) 컴포넌트](#controlled-components)를 사용하셔야 합니다.
|
||||
|
||||
|
||||
## 심화 주제
|
||||
|
||||
|
||||
### 왜 제어되는 컴포넌트인가요?
|
||||
|
||||
React에서 `<input>`같은 폼 컴포넌트를 사용하면, 전통적인 폼 HTML을 쓸 때에는 없던 어려운 문제가 있습니다. 예를 들어 HTML에서
|
||||
@@ -123,7 +124,6 @@ HTML과 다르게, React 컴포넌트는 초기화 시점 뿐만 아니라, 어
|
||||
|
||||
이 메소드가 어떤 시점에도 뷰를 기술하기 때문에, 텍스트 input의 값은 *언제나* `Untitled`입니다.
|
||||
|
||||
|
||||
### 왜 Textarea에 value를 사용하나요?
|
||||
|
||||
HTML에서, `<textarea>`의 값은 보통 그것의 자식들로 설정됩니다.
|
||||
@@ -141,7 +141,6 @@ HTML에서는 이렇게 하면 여러 줄의 값을 쉽게 개발자가 넣을
|
||||
|
||||
자식들을 사용하기로 *했다면*, 자식들은 `defaultValue`처럼 동작할 것입니다.
|
||||
|
||||
|
||||
### 왜 Select에 value를 사용하나요?
|
||||
|
||||
HTML `<select>`에서 선택된 `<option>`은 보통 option의 `selected` 어트리뷰트로 기술됩니다. React에서는 컴포넌트를 관리하기 쉽게 하기 위해, 다음 형식이 대신 채용됐습니다.
|
||||
|
||||
@@ -32,10 +32,9 @@ Like all DOM events, the `onChange` prop is supported on all native components a
|
||||
>
|
||||
> For `<input>` and `<textarea>`, `onChange` supersedes — and should generally be used instead of — the DOM's built-in [`oninput`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput) event handler.
|
||||
|
||||
|
||||
## Controlled Components
|
||||
|
||||
An `<input>` with `value` set is a *controlled* component. In a controlled `<input>`, the value of the rendered element will always reflect the `value` prop. For example:
|
||||
A **controlled** `<input>` has a `value` prop. Rendering a controlled `<input>` will reflect the value of the `value` prop.
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
@@ -43,7 +42,7 @@ An `<input>` with `value` set is a *controlled* component. In a controlled `<inp
|
||||
}
|
||||
```
|
||||
|
||||
This will render an input that always has a value of `Hello!`. Any user input will have no effect on the rendered element because React has declared the value to be `Hello!`. If you wanted to update the value in response to user input, you could use the `onChange` event:
|
||||
User input will have no effect on the rendered element because React has declared the value to be `Hello!`. To update the value in response to user input, you could use the `onChange` event:
|
||||
|
||||
```javascript
|
||||
getInitialState: function() {
|
||||
@@ -53,12 +52,17 @@ This will render an input that always has a value of `Hello!`. Any user input wi
|
||||
this.setState({value: event.target.value});
|
||||
},
|
||||
render: function() {
|
||||
var value = this.state.value;
|
||||
return <input type="text" value={value} onChange={this.handleChange} />;
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.value}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
In this example, we are simply accepting the newest value provided by the user and updating the `value` prop of the `<input>` component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. For example:
|
||||
In this example, we are accepting the value provided by the user and updating the `value` prop of the `<input>` component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. For example:
|
||||
|
||||
```javascript
|
||||
handleChange: function(event) {
|
||||
@@ -66,16 +70,17 @@ In this example, we are simply accepting the newest value provided by the user a
|
||||
}
|
||||
```
|
||||
|
||||
This would accept user input but truncate the value to the first 140 characters.
|
||||
This would accept user input and truncate the value to the first 140 characters.
|
||||
|
||||
A **Controlled** component does not maintain its own internal state; the component renders purely based on props.
|
||||
|
||||
### Potential Issues With Checkboxes and Radio Buttons
|
||||
|
||||
Be aware that, in an attempt to normalise change handling for checkbox and radio inputs, React uses a `click` event in place of a `change` event. For the most part this behaves as expected, except when calling `preventDefault` in a `change` handler. `preventDefault` stops the browser from visually updating the input, even if `checked` gets toggled. This can be worked around either by removing the call to `preventDefault`, or putting the toggle of `checked` in a `setTimeout`.
|
||||
|
||||
Be aware that, in an attempt to normalize change handling for checkbox and radio inputs, React uses a `click` event in place of a `change` event. For the most part this behaves as expected, except when calling `preventDefault` in a `change` handler. `preventDefault` stops the browser from visually updating the input, even if `checked` gets toggled. This can be worked around either by removing the call to `preventDefault`, or putting the toggle of `checked` in a `setTimeout`.
|
||||
|
||||
## Uncontrolled Components
|
||||
|
||||
An `<input>` that does not supply a `value` (or sets it to `null`) is an *uncontrolled* component. In an uncontrolled `<input>`, the value of the rendered element will reflect the user's input. For example:
|
||||
An `<input>` without a `value` property is an *uncontrolled* component:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
@@ -85,6 +90,8 @@ An `<input>` that does not supply a `value` (or sets it to `null`) is an *uncont
|
||||
|
||||
This will render an input that starts off with an empty value. Any user input will be immediately reflected by the rendered element. If you wanted to listen to updates to the value, you could use the `onChange` event just like you can with controlled components.
|
||||
|
||||
An **uncontrolled** component maintains its own internal state.
|
||||
|
||||
### Default Value
|
||||
|
||||
If you want to initialize the component with a non-empty value, you can supply a `defaultValue` prop. For example:
|
||||
@@ -95,18 +102,16 @@ If you want to initialize the component with a non-empty value, you can supply a
|
||||
}
|
||||
```
|
||||
|
||||
This example will function much like the **Controlled Components** example above.
|
||||
This example will function much like the **Uncontrolled Components** example above.
|
||||
|
||||
Likewise, `<input>` supports `defaultChecked` and `<select>` supports `defaultValue`.
|
||||
Likewise, `<input type="checkbox">` and `<input type="radio">` support `defaultChecked`, and `<select>` supports `defaultValue`.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> The `defaultValue` and `defaultChecked` props are only used during initial render. If you need to update the value in a subsequent render, you will need to use a [controlled component](#controlled-components).
|
||||
|
||||
|
||||
## Advanced Topics
|
||||
|
||||
|
||||
### Why Controlled Components?
|
||||
|
||||
Using form components such as `<input>` in React presents a challenge that is absent when writing traditional form HTML. For example, in HTML:
|
||||
@@ -127,7 +132,6 @@ Unlike HTML, React components must represent the state of the view at any point
|
||||
|
||||
Since this method describes the view at any point in time, the value of the text input should *always* be `Untitled`.
|
||||
|
||||
|
||||
### Why Textarea Value?
|
||||
|
||||
In HTML, the value of `<textarea>` is usually set using its children:
|
||||
@@ -145,7 +149,6 @@ For HTML, this easily allows developers to supply multiline values. However, sin
|
||||
|
||||
If you *do* decide to use children, they will behave like `defaultValue`.
|
||||
|
||||
|
||||
### Why Select Value?
|
||||
|
||||
The selected `<option>` in an HTML `<select>` is normally specified through that option's `selected` attribute. In React, in order to make components easier to manipulate, the following format is adopted instead:
|
||||
|
||||
@@ -7,43 +7,42 @@ next: working-with-the-browser-zh-CN.html
|
||||
---
|
||||
|
||||
诸如 `<input>`、`<textarea>`、`<option>` 这样的表单组件不同于其他组件,因为他们可以通过用户交互发生变化。这些组件提供的界面使响应用户交互的表单数据处理更加容易。
|
||||
|
||||
|
||||
关于 `<form>` 事件详情请查看 [表单事件](/react/docs/events-zh-CN.html#form-events)。
|
||||
|
||||
## 交互属性
|
||||
|
||||
## 交互属性
|
||||
|
||||
表单组件支持几个受用户交互影响的属性:
|
||||
|
||||
|
||||
* `value`,用于 `<input>`、`<textarea>` 组件。
|
||||
* `checked`,用于类型为 `checkbox` 或者 `radio` 的 `<input>` 组件。
|
||||
* `selected`,用于 `<option>` 组件。
|
||||
|
||||
在 HTML 中,`<textarea>` 的值通过子节点设置;在 React 中则应该使用 `value` 代替。
|
||||
在 HTML 中,`<textarea>` 的值通过子节点设置;在 React 中则应该使用 `value` 代替。
|
||||
|
||||
表单组件可以通过 `onChange` 回调函数来监听组件变化。当用户做出以下交互时,`onChange` 执行并通过浏览器做出响应:
|
||||
|
||||
|
||||
* `<input>` 或 `<textarea>` 的 `value` 发生变化时。
|
||||
* `<input>` 的 `checked` 状态改变时。
|
||||
* `<option>` 的 `selected` 状态改变时。
|
||||
|
||||
和所有 DOM 事件一样,所有的 HTML 原生组件都支持 `onChange` 属性,而且可以用来监听冒泡的 `change` 事件。
|
||||
|
||||
|
||||
和所有 DOM 事件一样,所有的 HTML 原生组件都支持 `onChange` 属性,而且可以用来监听冒泡的 `change` 事件。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 对于 `<input>` and `<textarea>`, `onChange` 替代 — 一般应该用来替代 — the DOM's 内建的 [`oninput`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput) 事件处理。
|
||||
> 对于 `<input>` and `<textarea>`, `onChange` 取代 — 一般应该用来替代 — DOM内建的 [`oninput`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput) 事件处理。
|
||||
|
||||
|
||||
## 受限组件
|
||||
## 受控组件
|
||||
|
||||
设置了 `value` 的 `<input>` 是一个*受限*组件。 对于受限的 `<input>`,渲染出来的 HTML 元素始终保持 `value` 属性的值。例如:
|
||||
一个*受控*的 `<input>` 有一个 `value` prop。渲染一个受控 `<input>` 会反映 `value` prop 的值。
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
return <input type="text" value="Hello!" />;
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码将渲染出一个值为 `Hello!` 的 input 元素。用户在渲染出来的元素里输入任何值都不起作用,因为 React 已经赋值为 `Hello!`。如果想响应更新用户输入的值,就得使用 `onChange` 事件:
|
||||
|
||||
用户输入在被渲染的元素里将没有作用,因为 React 已经声明值为 `Hello!`。要更新 value 来响应用户输入,你可以使用 `onChange` 事件:
|
||||
|
||||
```javascript
|
||||
getInitialState: function() {
|
||||
@@ -53,12 +52,17 @@ next: working-with-the-browser-zh-CN.html
|
||||
this.setState({value: event.target.value});
|
||||
},
|
||||
render: function() {
|
||||
var value = this.state.value;
|
||||
return <input type="text" value={value} onChange={this.handleChange} />;
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.value}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码中,React 将用户输入的值更新到 `<input>` 组件的 `value` 属性。这样实现响应或者验证用户输入的界面就很容易了。例如:
|
||||
在这个例子中,我们接受用户提供的值并更新 `<input>` 组件的 `value` prop。这个模式使实现响应或者验证用户输入的界面更容易。例如:
|
||||
|
||||
```javascript
|
||||
handleChange: function(event) {
|
||||
@@ -68,14 +72,15 @@ next: working-with-the-browser-zh-CN.html
|
||||
|
||||
上面的代码接受用户输入,并截取前 140 个字符。
|
||||
|
||||
受控组件不维持一个自己的内部状态;它单纯的基于 props 渲染。
|
||||
|
||||
### 复选框与单选按钮的潜在问题
|
||||
|
||||
当心,在力图标准化复选框与单选按钮的变换处理中,React使用`click` 事件代替 `change` 事件。在大多数情况下它们表现的如同预期,除了在`change` handler中调用`preventDefault` 。`preventDefault` 阻止了浏览器视觉上更新输入,即使`checked`被触发。变通的方式是要么移除`preventDefault`的调用,要么把`checked` 的触发放在一个`setTimeout`里。
|
||||
|
||||
|
||||
## 不受限组件
|
||||
## 不受控组件
|
||||
|
||||
没有设置 `value`(或者设为 `null`) 的 `<input>` 组件是一个*不受限*组件。对于不受限的 `<input>` 组件,渲染出来的元素直接反应用户输入。例如:
|
||||
一个没有 `value` 属性的 `<input>` 是一个不*受控*组件:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
@@ -83,7 +88,9 @@ next: working-with-the-browser-zh-CN.html
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码将渲染出一个空值的输入框,用户输入将立即反应到元素上。和受限元素一样,使用 `onChange` 事件可以监听值的变化。
|
||||
上面的代码将渲染出一个空值的输入框,用户输入将立即反应到元素上。和受控元素一样,使用 `onChange` 事件可以监听值的变化。
|
||||
|
||||
*不受控*组件维持它自己的内部状态。
|
||||
|
||||
### 默认值
|
||||
|
||||
@@ -95,29 +102,27 @@ next: working-with-the-browser-zh-CN.html
|
||||
}
|
||||
```
|
||||
|
||||
这个例子会像上面的**Controlled Components** 例子一样运行。
|
||||
这个例子会像上面的 **不受控组件** 例子一样运行。
|
||||
|
||||
同样的, `<input>` 支持 `defaultChecked` 、 `<select>` 支持 `defaultValue`.
|
||||
同样的, `<input type="checkbox">` 和 `<input type="radio">` 支持 `defaultChecked` 、 `<select>` 支持 `defaultValue`.
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> `defaultValue` 和 `defaultChecked` props 只能在内部渲染时被使用。 如果你需要在随后的渲染更新值, 你需要使用 [受限组件](#受限组件).
|
||||
|
||||
> `defaultValue` 和 `defaultChecked` props 只能在内部渲染时被使用。 如果你需要在随后的渲染更新值, 你需要使用 [受控组件](#受控组件).
|
||||
|
||||
## 高级主题
|
||||
|
||||
|
||||
### 为什么使用受限组件?
|
||||
### 为什么使用受控组件?
|
||||
|
||||
在 React 中使用诸如 `<input>` 的表单组件时,遇到了一个在传统 HTML 中没有的挑战。比如下面的代码:
|
||||
在 React 中使用诸如 `<input>` 的表单组件时,遇到了一个在传统 HTML 中没有的挑战。比如下面的代码:
|
||||
|
||||
```html
|
||||
<input type="text" name="title" value="Untitled" />
|
||||
```
|
||||
|
||||
在 HTML 中将渲染 *初始值* 为 `Untitled` 的输入框。用户改变输入框的值时,节点的 `value` 属性( *property*)将随之变化,但是 `node.getAttribute('value')` 还是会返回初始设置的值 `Untitled`.
|
||||
它渲染一个*初始值*为 `Untitled` 的输入框。当用户改变输入框的值时,节点的 `value` 属性( *property*)将随之变化,但是 `node.getAttribute('value')` 还是会返回初始设置的值 `Untitled`.
|
||||
|
||||
与 HTML 不同,React 组件必须在任何时间点描绘视图的状态,而不仅仅是在初始化时。比如在 React 中:
|
||||
与 HTML 不同,React 组件必须在任何时间点表现视图的状态,而不仅仅是在初始化时。比如在 React 中:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
@@ -125,8 +130,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
}
|
||||
```
|
||||
|
||||
该方法在任何时间点渲染组件以后,输入框的值就应该 *始终* 为 `Untitled`。
|
||||
|
||||
既然这个方法描述了在任意时间点上的视图,那么文本输入框的值就应该*始终*为 `Untitled`。
|
||||
|
||||
### 为什么 `<textarea>` 使用 `value` 属性?
|
||||
|
||||
@@ -136,8 +140,8 @@ next: working-with-the-browser-zh-CN.html
|
||||
<!-- 反例:在 React 中不要这样使用! -->
|
||||
<textarea name="description">This is the description.</textarea>
|
||||
```
|
||||
|
||||
对 HTML 而言,让开发者设置多行的值很容易。但是,React 是 JavaScript,没有字符限制,可以使用 `\n` 实现换行。简言之,React 已经有 `value`、`defaultValue` 属性,`</textarea>` 组件的子节点扮演什么角色就有点模棱两可了。基于此, 设置 `<textarea>` 值时不应该使用子节点:
|
||||
|
||||
对 HTML 而言,让开发者设置多行的值很容易。但是,React 是 JavaScript,没有字符串限制,可以使用 `\n` 实现换行。简言之,React 已经有 `value`、`defaultValue` 属性,`</textarea>` 组件的子节点扮演什么角色就有点模棱两可了。基于此, 设置 `<textarea>` 值时不应该使用子节点:
|
||||
|
||||
```javascript
|
||||
<textarea name="description" value="This is a description." />
|
||||
@@ -145,8 +149,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
|
||||
如果 *非要* 使用子节点,效果和使用 `defaultValue` 一样。
|
||||
|
||||
|
||||
### 为什么 `<select>` 使用 `value` 属性
|
||||
### 为什么 `<select>` 使用 `value` 属性
|
||||
|
||||
HTML 中 `<select>` 通常使用 `<option>` 的 `selected` 属性设置选中状态;React 为了更方面的控制组件,采用以下方式代替:
|
||||
|
||||
@@ -158,7 +161,7 @@ HTML 中 `<select>` 通常使用 `<option>` 的 `selected` 属性设置选中状
|
||||
</select>
|
||||
```
|
||||
|
||||
如果是不受限组件,则使用 `defaultValue`。
|
||||
如果是不受控组件,则使用 `defaultValue`。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
|
||||
@@ -32,7 +32,7 @@ var MyComponent = React.createClass({
|
||||
ReactDOM.findDOMNode(this.refs.myTextInput).focus();
|
||||
},
|
||||
render: function() {
|
||||
// この参照属性はコンポーネントがマウントされた時に、
|
||||
// この参照属性はコンポーネントがマウントされた時に、
|
||||
// this.refs のコンポーネントへの参照を追加します。
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -11,7 +11,7 @@ React는 대부분의 경우 직접 DOM을 다루지 않아도 될만큼 강력
|
||||
|
||||
## 가상의 DOM
|
||||
|
||||
React는 DOM을 직접 다루지 않기 때문에 굉장히 빠릅니다. React는 메모리에(in-memory) DOM의 표상(representation)을 관리합니다. `render()` 메소드는 DOM의 *서술*를 반환하고, React는 이를 메모리에 있는 DOM의 표상과 비교(diff)해 가장 빠른 방식으로 계산해서 브라우저를 업데이트해 줍니다.
|
||||
React는 DOM을 직접 다루지 않기 때문에 매우 빠릅니다. React는 메모리에(in-memory) DOM의 표상(representation)을 관리합니다. `render()` 메소드는 사실은 DOM의 *서술*를 반환하고, React는 이를 메모리에 있는 DOM의 표상과 비교해 가장 빠른 방식으로 계산해서 브라우저를 업데이트해 줍니다.
|
||||
|
||||
게다가 React는 브라우저의 괴악함(quirks)에도 불구하고 모든 이벤트 객체가 W3C 명세를 보장하도록 통합적인 이벤트 시스템을 구현했습니다. 모든 것이 일관된 방식으로 일어나고(bubbles) 효율적으로 크로스 브라우징을 수행합니다. 심지어 IE8에서도 HTML5 이벤트를 사용할 수 있습니다!
|
||||
|
||||
@@ -20,45 +20,7 @@ React는 DOM을 직접 다루지 않기 때문에 굉장히 빠릅니다. React
|
||||
|
||||
## Refs와 findDOMNode()
|
||||
|
||||
브라우저와 상호 작용하려면 DOM 노드에 대한 참조가 필요합니다. React는 `ReactDOM.findDOMNode(component)` 함수를 갖고 있으며, 이를 통해서 컴포넌트의 DOM 노드의 참조를 얻을 수 있습니다.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> `findDOMNode()`는 마운트 된 컴포넌트에서만 동작합니다 (DOM에 배치된 컴포넌트를 말합니다). 아직 마운트 되지 않은 컴포넌트에서 이를 호출하려고 하면 (컴포넌트가 아직 생성되기 이전인 `render()` 시점에 `findDOMNode()`를 호출한다든가) 예외가 발생합니다.
|
||||
|
||||
React 컴포넌트에 대한 참조는 현재의 React 컴포넌트를 위해 `this`를, 소유한 컴포넌트의 참조를 얻기 위해 refs를 사용해 얻을 수 있습니다. 다음과 같이 동작합니다:
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// raw DOM API를 사용해 명시적으로 텍스트 인풋을 포커스 합니다.
|
||||
ReactDOM.findDOMNode(this.refs.myTextInput).focus();
|
||||
},
|
||||
render: function() {
|
||||
// ref 어트리뷰트는 컴포넌트가 마운트되면 그에 대한 참조를 this.refs에 추가합니다.
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref="myTextInput" />
|
||||
<input
|
||||
type="button"
|
||||
value="Focus the text input"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<MyComponent />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## Refs 심화
|
||||
|
||||
[refs 심화](/react/docs/more-about-refs-ko-KR.html) 문서에서 refs를 효율적으로 사용하는 법을 포함해 더 많은 내용을 익혀보세요.
|
||||
브라우저와 상호 작용하려면 DOM 노드에 대한 참조가 필요합니다. `ref`를 어떤 엘리먼트에도 붙일 수 있으며, 이를 통해 컴포넌트 **지원 인스턴스**를 참조 할 수 있습니다. 이는 컴포넌트에 필수 적인 기능을 호출할 때나 기저의 DOM 노드에 접근하고 싶을 때 유용합니다. [refs에서 컴포넌트로](/react/docs/more-about-refs-ko-KR.html) 문서에서 refs를 효율적으로 사용하는 법을 포함해 더 많은 내용을 익혀보세요.
|
||||
|
||||
|
||||
<a name="component-lifecycle"></a>
|
||||
@@ -72,14 +34,12 @@ ReactDOM.render(
|
||||
|
||||
React는 이 프로세스에 훅을 지정할 수 있는 생명주기 메소드를 제공합니다. 발생 직전 시점을 위한 **will** 메소드, 발생 직후 시점을 위한 **did** 메소드가 있습니다.
|
||||
|
||||
|
||||
### Mounting
|
||||
|
||||
* `getInitialState(): object`는 컴포넌트가 마운트되기 전에 호출됩니다. 상태기반 컴포넌트는 이를 구현하고 초기 상태 데이터를 리턴합니다.
|
||||
* `componentWillMount()`는 마운팅되기 직전에 호출됩니다.
|
||||
* `componentDidMount()`는 마운팅 직후 호출됩니다. 초기화에 필요한 DOM 노드는 이곳에 있어야 합니다.
|
||||
|
||||
|
||||
### Updating
|
||||
|
||||
* `componentWillReceiveProps(object nextProps)`는 마운트된 컴포넌트가 새로운 props을 받을 때 호출됩니다. 이 메소드는 `this.props`와 `nextProps`을 비교하여 `this.setState()`를 사용해 상태 변환을 수행하는데 사용되야 합니다.
|
||||
@@ -87,19 +47,15 @@ React는 이 프로세스에 훅을 지정할 수 있는 생명주기 메소드
|
||||
* `componentWillUpdate(object nextProps, object nextState)`는 업데이트가 발생하기 직전에 호출됩니다. 이 시점에는 `this.setState()`를 호출할 수 없습니다.
|
||||
* `componentDidUpdate(object prevProps, object prevState)`는 업데이트가 발생한 후 즉시 호출됩니다.
|
||||
|
||||
|
||||
### Unmounting
|
||||
|
||||
* `componentWillUnmount()`는 컴포넌트가 언마운트되어 파괴되기 직전에 호출됩니다. 정리(Cleanup)는 여기서 처리해야 합니다.
|
||||
|
||||
|
||||
### Mounted 메소드
|
||||
|
||||
_마운트된_ 합성 컴포넌트들은 다음과 같은 메소드를 지원합니다:
|
||||
|
||||
* `findDOMNode(): DOMElement`는 렌더링 된 DOM 노드에 대한 참조를 얻기 위해 모든 마운트된 컴포넌트에서 호출할 수 있습니다.
|
||||
* `forceUpdate()`는 `this.setState`를 사용하지 않고 컴포넌트 state의 더 깊은 측면(deeper aspect)의 변경된 것을 알고 있을 때 모든 마운트된 컴포넌트에서 호출할 수 있습니다.
|
||||
|
||||
* `component.forceUpdate()`는 `this.setState()`를 사용하지 않고 변경된 컴포넌트의 상태의 변경을 적용하고 싶을 때 마운트된 컴포넌트에서 사용할 수 있습니다.
|
||||
|
||||
## 브라우저 지원과 Polyfill
|
||||
|
||||
@@ -107,7 +63,6 @@ _마운트된_ 합성 컴포넌트들은 다음과 같은 메소드를 지원합
|
||||
|
||||
그 철학에 더하여, 우리는 또한 JS 라이브러리의 저자로서 polyfill을 라이브러리에 포함해서 배포하지 않습니다. 만약 모든 라이브러리가 이런 짓을 하면, 같은 polyfill을 여러 번 내리게 되어 쓸모없이 크기만 차지하는 죽은 코드들을 만들 것 입니다. 당신의 제품이 구식 브라우저를 지원해야한다면, [es5-shim](https://github.com/es-shims/es5-shim) 같은 녀석을 사용할 기회가 있었을 겁니다.
|
||||
|
||||
|
||||
### Polyfill은 구식 브라우저를 지원하기 위해 필요하다
|
||||
|
||||
[kriskowal's es5-shim](https://github.com/es-shims/es5-shim)의 `es5-shim.js`는 React에 필요한 다음의 기능을 제공합니다:
|
||||
@@ -134,11 +89,9 @@ _마운트된_ 합성 컴포넌트들은 다음과 같은 메소드를 지원합
|
||||
|
||||
`<section>`, `<article>`, `<nav>`, `<header>`, `<footer>`등 HTML5 엘리먼트를 IE8에서 이용하려면 [html5shiv](https://github.com/aFarkas/html5shiv)같은 스크립트가 추가로 필요합니다.
|
||||
|
||||
|
||||
### 크로스 브라우징 이슈
|
||||
|
||||
React가 브라우저별 차이점을 썩 잘 추상화하긴 했지만 일부는 한정적이거나 우리가 발견하지 못한 이상한(quirky) 동작을 보여주기도 합니다.
|
||||
|
||||
React가 브라우저별 차이점을 썩 잘 추상화하긴 했지만 일부는 한정적이거나 우리가 발견하지 못한 이상한(quirky) 동작을 보여주기도 합니다.
|
||||
|
||||
#### IE8에서의 onScroll 이벤트
|
||||
|
||||
|
||||
@@ -8,21 +8,18 @@ next: more-about-refs.html
|
||||
|
||||
React provides powerful abstractions that free you from touching the DOM directly in most cases, but sometimes you simply need to access the underlying API, perhaps to work with a third-party library or existing code.
|
||||
|
||||
|
||||
## The Virtual DOM
|
||||
|
||||
React is so fast because it never talks to the DOM directly. React maintains a fast in-memory representation of the DOM. `render()` methods return a *description* of the DOM, and React can diff this description with the in-memory representation to compute the fastest way to update the browser.
|
||||
React is very fast because it never talks to the DOM directly. React maintains a fast in-memory representation of the DOM. `render()` methods actually return a *description* of the DOM, and React can compare this description with the in-memory representation to compute the fastest way to update the browser.
|
||||
|
||||
Additionally, React implements a full synthetic event system such that all event objects are guaranteed to conform to the W3C spec despite browser quirks, and everything bubbles consistently and efficiently across browsers. You can even use some HTML5 events in IE8!
|
||||
Additionally, React implements a full synthetic event system such that all event objects are guaranteed to conform to the W3C spec despite browser quirks, and everything bubbles consistently and efficiently across browsers. You can even use some HTML5 events in older browsers that don't ordinarily support them!
|
||||
|
||||
Most of the time you should stay within React's "faked browser" world since it's more performant and easier to reason about. However, sometimes you simply need to access the underlying API, perhaps to work with a third-party library like a jQuery plugin. React provides escape hatches for you to use the underlying DOM API directly.
|
||||
|
||||
|
||||
## Refs and findDOMNode()
|
||||
|
||||
To interact with the browser, you'll need a reference to a DOM node. You can attach a `ref` to any element, which allows you to reference the **backing instance** of the component. This is useful if you need to invoke imperative functions on the component, or want to access the underlying DOM nodes. To learn more about refs, including ways to use them effectively, see our [refs to components](/react/docs/more-about-refs.html) documentation.
|
||||
|
||||
|
||||
## Component Lifecycle
|
||||
|
||||
Components have three main parts of their lifecycle:
|
||||
@@ -33,14 +30,12 @@ Components have three main parts of their lifecycle:
|
||||
|
||||
React provides lifecycle methods that you can specify to hook into this process. We provide **will** methods, which are called right before something happens, and **did** methods which are called right after something happens.
|
||||
|
||||
|
||||
### Mounting
|
||||
|
||||
* `getInitialState(): object` is invoked before a component is mounted. Stateful components should implement this and return the initial state data.
|
||||
* `componentWillMount()` is invoked immediately before mounting occurs.
|
||||
* `componentDidMount()` is invoked immediately after mounting occurs. Initialization that requires DOM nodes should go here.
|
||||
|
||||
|
||||
### Updating
|
||||
|
||||
* `componentWillReceiveProps(object nextProps)` is invoked when a mounted component receives new props. This method should be used to compare `this.props` and `nextProps` to perform state transitions using `this.setState()`.
|
||||
@@ -48,61 +43,18 @@ React provides lifecycle methods that you can specify to hook into this process.
|
||||
* `componentWillUpdate(object nextProps, object nextState)` is invoked immediately before updating occurs. You cannot call `this.setState()` here.
|
||||
* `componentDidUpdate(object prevProps, object prevState)` is invoked immediately after updating occurs.
|
||||
|
||||
|
||||
### Unmounting
|
||||
|
||||
* `componentWillUnmount()` is invoked immediately before a component is unmounted and destroyed. Cleanup should go here.
|
||||
|
||||
|
||||
### Mounted Methods
|
||||
|
||||
_Mounted_ composite components also support the following method:
|
||||
|
||||
* `component.forceUpdate()` can be invoked on any mounted component when you know that some deeper aspect of the component's state has changed without using `this.setState()`.
|
||||
|
||||
## Browser Support
|
||||
|
||||
## Browser Support and Polyfills
|
||||
React supports most popular browsers, including Internet Explorer 9 and above.
|
||||
|
||||
At Facebook, we support older browsers, including IE8. We've had polyfills in place for a long time to allow us to write forward-thinking JS. This means we don't have a bunch of hacks scattered throughout our codebase and we can still expect our code to "just work". For example, instead of seeing `+new Date()`, we can just write `Date.now()`. Since the open source React is the same as what we use internally, we've carried over this philosophy of using forward thinking JS.
|
||||
|
||||
In addition to that philosophy, we've also taken the stance that we, as authors of a JS library, should not be shipping polyfills as a part of our library. If every library did this, there's a good chance you'd be sending down the same polyfill multiple times, which could be a sizable chunk of dead code. If your product needs to support older browsers, chances are you're already using something like [es5-shim](https://github.com/es-shims/es5-shim).
|
||||
|
||||
|
||||
### Polyfills Needed to Support Older Browsers
|
||||
|
||||
`es5-shim.js` from [kriskowal's es5-shim](https://github.com/es-shims/es5-shim) provides the following that React needs:
|
||||
|
||||
* `Array.isArray`
|
||||
* `Array.prototype.every`
|
||||
* `Array.prototype.forEach`
|
||||
* `Array.prototype.indexOf`
|
||||
* `Array.prototype.map`
|
||||
* `Date.now`
|
||||
* `Function.prototype.bind`
|
||||
* `Object.keys`
|
||||
* `String.prototype.split`
|
||||
* `String.prototype.trim`
|
||||
|
||||
`es5-sham.js`, also from [kriskowal's es5-shim](https://github.com/es-shims/es5-shim), provides the following that React needs:
|
||||
|
||||
* `Object.create`
|
||||
* `Object.freeze`
|
||||
|
||||
The unminified build of React needs the following from [paulmillr's console-polyfill](https://github.com/paulmillr/console-polyfill).
|
||||
|
||||
* `console.*`
|
||||
|
||||
When using HTML5 elements in IE8 including `<section>`, `<article>`, `<nav>`, `<header>`, and `<footer>`, it's also necessary to include [html5shiv](https://github.com/aFarkas/html5shiv) or a similar script.
|
||||
|
||||
|
||||
### Cross-browser Issues
|
||||
|
||||
Although React is pretty good at abstracting browser differences, some browsers are limited or present quirky behaviors that we couldn't find a workaround for.
|
||||
|
||||
|
||||
#### onScroll event on IE8
|
||||
|
||||
On IE8 the `onScroll` event doesn't bubble and IE8 doesn't have an API to define handlers to the capturing phase of an event, meaning there is no way for React to listen to these events.
|
||||
Currently a handler to this event is ignored on IE8.
|
||||
|
||||
See the [onScroll doesn't work in IE8](https://github.com/facebook/react/issues/631) GitHub issue for more information.
|
||||
(We don't support older browsers that don't support ES5 methods, but you may find that your apps do work in older browsers if polyfills such as [es5-shim and es5-sham](https://github.com/es-shims/es5-shim) are included in the page. You're on your own if you choose to take this path.)
|
||||
|
||||
@@ -8,59 +8,17 @@ next: more-about-refs-zh-CN.html
|
||||
|
||||
React提供了强大的抽象机制使你在大多数情况下免于直接接触DOM,但有时你仅仅只需要访问底层API,也许是为了与第三方库或者已有的代码协作。
|
||||
|
||||
## 虚拟DOM
|
||||
|
||||
## 虚拟DOM
|
||||
|
||||
React如此快速是因为它从不直接操作DOM。React维持了一个快速的内存中的DOM表示。`render()` 方法返回一个DOM的*描述*,然后React能根据内存中的描述diff此描述来计算出最快速的方法更新浏览器。
|
||||
React非常快速是因为它从不直接操作DOM。React维持了一个快速的内存中的DOM表示。`render()` 方法实际上返回一个对DOM的*描述*,然后React能根据内存中的“描述”来比较此“描述”以计算出最快速的方法更新浏览器。
|
||||
|
||||
此外,React实现了一个完备的合成事件(synthetic event)系统,以使得所有的事件对象都被保证符合W3C细则,而不论各个浏览器的怪癖,并且所有事件跨浏览器地一致并高效的冒泡(bubbles),你甚至能在IE8里使用一些HTML5事件!
|
||||
|
||||
大多数时间你应该和React的"伪造浏览器"呆在一起,因为它更高性能并且容易推理。然而,有时你只需要访问底层API,或许是为了与第三方库比如一个jQuery插件协作。React为你提供了安全仓口来直接使用底层API。
|
||||
|
||||
|
||||
## Refs 和 findDOMNode()
|
||||
|
||||
为了与浏览器互动,你需要一个指向DOM node的引用。React有一个函数`ReactDOM.findDOMNode(component)` ,你能调用以得到一个指向指向组件的DOM node的引用。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> `findDOMNode()` 只作用于已挂载的组件(即,已经放置于DOM中的组件)。如果你尝试在还没有被挂载的组件上调用此函数(比如在`render()` 里有待被创建的组件上调用`findDOMNode()`将会抛出一个异常)
|
||||
|
||||
为了获得一个指向React组件的引用,你可以要么使用`this` 来得到当前React组件,要么使用refs来引用你拥有的组件。它们像这样工作:
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// 明确的强制text input使用原生DOM API。
|
||||
ReactDOM.findDOMNode(this.refs.myTextInput).focus();
|
||||
},
|
||||
render: function() {
|
||||
// 当组件被挂载时
|
||||
// ref属性给this.refs添加了一个指向指向组件的引用
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref="myTextInput" />
|
||||
<input
|
||||
type="button"
|
||||
value="Focus the text input"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<MyComponent />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 更多关于Refs
|
||||
|
||||
要学习更多有关refs,包括更有效使用它们的方法,请参见[more about refs](/react/docs/more-about-refs.html) 文档。
|
||||
|
||||
为了与浏览器互动,你需要一个指向DOM node的引用。你可以连接一个 `ref` 到任何的元素,这允许你引用 组件的 **backing instance** 。它很有用,如果你需要在组件上调用命令式函数,或者想访问底层的DOM节点。要了解很多关于 refs,包括更有效使用他们的方法,请查看我们的 [关于Refs的更多内容](/react/docs/more-about-refs-zh-CN.html) 文档。
|
||||
|
||||
## 组件的生命周期
|
||||
|
||||
@@ -72,34 +30,28 @@ ReactDOM.render(
|
||||
|
||||
React提供生命周期方法,以便你可以指定钩挂到这个过程上。我们提供了 **will** 方法,该方法在某事发生前被调用,**did**方法,在某事发生后被调用。
|
||||
|
||||
|
||||
### 挂载
|
||||
|
||||
* `getInitialState(): object` 在组件挂载前被调用. 有状态组件(Stateful components) 应该实现此函数并返回初始state的数据。
|
||||
* `componentWillMount()` 在挂载发生前被立即调用。
|
||||
* `componentDidMount()` 在挂载发生后被立即调用。 需要DOM node的初始化应该放在这里。
|
||||
|
||||
* `componentWillMount()` 在挂载发生前被立即调用。
|
||||
* `componentDidMount()` 在挂载发生后被立即调用。 需要DOM node的初始化应该放在这里。
|
||||
|
||||
### 更新
|
||||
|
||||
* `componentWillReceiveProps(object nextProps)` 当挂载的组件接收到新的props时被调用。此方法应该被用于比较`this.props` 和 `nextProps`以用于使用`this.setState()`执行状态转换。
|
||||
* `shouldComponentUpdate(object nextProps, object nextState): boolean` 当组件决定任何改变是否要更新到DOM时被调用。作为一个优化实现比较`this.props` 和 `nextProps` 、`this.state` 和 `nextState` ,如果React应该跳过更新,返回`false`。
|
||||
* `shouldComponentUpdate(object nextProps, object nextState): boolean` 当组件决定任何改变是否要更新到DOM时被调用。作为一个优化实现比较`this.props` 和 `nextProps` 、`this.state` 和 `nextState` ,如果React应该跳过更新,返回`false`。
|
||||
* `componentWillUpdate(object nextProps, object nextState)` 在更新发生前被立即调用。你不能在此调用`this.setState()`。
|
||||
* `componentDidUpdate(object prevProps, object prevState)` 在更新发生后被立即调用。
|
||||
|
||||
|
||||
### 卸载
|
||||
|
||||
* `componentWillUnmount()` 在组件被卸载和摧毁后被立即调用。清理应该放在这里。
|
||||
|
||||
|
||||
### Mounted Methods
|
||||
### 已挂载的方法
|
||||
|
||||
_Mounted_ 复合组件同样支持以下方法:
|
||||
|
||||
* `findDOMNode(): DOMElement` 能够在任何已挂载的组件上调用以便于获取指向它渲染的DOM node的引用。
|
||||
* `forceUpdate()` 能在任何已挂载的组件上调用,当你知道一些更深层次的组件状态变化了但没有使用 `this.setState()`。
|
||||
|
||||
* `component.forceUpdate()` 可以在任何已挂载的组件上调用,在你知道 某些深处的组件状态被未使用 `this.setState()` 改变了时。
|
||||
|
||||
## 浏览器支持和填充物(polyfills)
|
||||
|
||||
@@ -107,8 +59,7 @@ _Mounted_ 复合组件同样支持以下方法:
|
||||
|
||||
除了这种哲学外,我们也采用了这样的立场,我们,作为一个JS库的作者,不应该把polyfills作为我们库的一部分。如果所有的库这样做,就有很大的机会发送同样的polyfill多次,这可能是一个相当大的无用代码。如果你的产品需要支援老的浏览器,你很有可能已经在使用某些东西比如[es5-shim](https://github.com/es-shims/es5-shim)。
|
||||
|
||||
|
||||
### 需要用来支持旧浏览器的Polyfills
|
||||
### 需要用来支持旧浏览器的Polyfills
|
||||
|
||||
来自 [kriskowal's es5-shim](https://github.com/es-shims/es5-shim)的`es5-shim.js` 提供了如下React需要的东西:
|
||||
|
||||
@@ -134,12 +85,10 @@ _Mounted_ 复合组件同样支持以下方法:
|
||||
|
||||
当在IE8里使用HTML5元素,包括`<section>`, `<article>`, `<nav>`, `<header>`, 和 `<footer>`, 同样必须包含[html5shiv](https://github.com/aFarkas/html5shiv) 或者类似的脚本。
|
||||
|
||||
|
||||
### 跨浏览器问题
|
||||
### 跨浏览器问题
|
||||
|
||||
尽管React在抽象浏览器不同时做的相当好,但一些浏览器被限制或者表现出怪异的行为,我们没能找到变通的方案解决。
|
||||
|
||||
|
||||
#### IE8的onScroll事件
|
||||
|
||||
在IE8`onScroll` 事件不冒泡,并且IE8没有定义事件捕获阶段handlers的API,意味React这没有办法去监听这些事件。
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
---
|
||||
id: more-about-refs
|
||||
title: Refs 的更多信息
|
||||
permalink: more-about-refs-zh-CN.html
|
||||
prev: working-with-the-browser-zh-CN.html
|
||||
next: tooling-integration-zh-CN.html
|
||||
---
|
||||
在从render方法返回你的UI结构之前,你可能想向从`render()` 返回的组件的实例“伸手”并调用其上的方法。通常,做类似这样的事情没必要在你的引用中制造数据流,因为Reactive的数据量确保最近的`props` 被发送到从 `render()` 返回的每个孩子中。然而,有些情况,这样做还是必须的或者有帮助的。
|
||||
|
||||
考虑一下情形,元素`<input />` (他存在于你的子层级中),当你更新它的值为一个空的字符串`''` 的时候,你告诉它获得焦点。
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
this.setState({userInput: ''}); //清空输入
|
||||
// 现在我们希望获取焦点<input />!
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click to Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
在这个例子中,注意我们是如何想要“告诉” input 一些事情的- 一些不能从它的props得到的东西。在这种情形下,我们想要“告诉”它,它现在也要改获取焦点了。然而,这里有些挑战。从`render()` 中返回的不是你实际组件的“孩子”组件,相反他是这些孩子在特定的时刻的一个*描述* - 一个快照。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
>记着,从`render()` 中返回的不是你的*实际*渲染地孩子实例。从`render()` 中返回的仅仅是在你的组件的子层次结构中的这些孩子实例一个特定时刻的*描述*。
|
||||
|
||||
|
||||
这意味着你绝不该“拿”从`render()` 中返回的东西去做什么事情并期望有什么意义。
|
||||
|
||||
```javascript
|
||||
// 反模式:不能工作.
|
||||
render: function() {
|
||||
var myInput = <input />; // 我打算在这个上调用这个方法
|
||||
this.rememberThisInput = myInput; // input在未来的某个时间点上!YAY!
|
||||
return (
|
||||
<div>
|
||||
<div>...</div>
|
||||
{myInput}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
在这个例子中,`<input />` 仅仅是 `<input />` 的一个*描述*。这个描述不能用来为`<input />`创建一个*真实的* **背后的实例**。
|
||||
|
||||
那么对 input 的*真实的* 背后的实例,该怎么说呢?
|
||||
|
||||
## ref 字符串属性
|
||||
|
||||
React 假设你可以向任何的从`render()` 中返回的组件附加一个特别的属性。这个特殊的属性允许你引用任何的从`render()` 返回的东西对于有的**背后的实例**。而且保证在任何时间点都是合适的实例。
|
||||
|
||||
简单的说就是:
|
||||
|
||||
|
||||
1. 给任何从`render()` 中返回的东西赋一个`ref` 的属性,如下所示:
|
||||
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
|
||||
2. 在其他的代码中(通常是事件处理代码中),通过 `this.refs` 来访问 **背后的实例** 如下所示:
|
||||
|
||||
```javascript
|
||||
this.refs.myInput
|
||||
```
|
||||
|
||||
通过调用`this.refs.myInput` 你可以直接方法这个组建的DOM。
|
||||
|
||||
|
||||
## ref 回调属性
|
||||
|
||||
`ref` 属性可以用一个回调函数来替换一个名字。当这个组件装载好之后立即执行。被引用的组件被作为一个参数传入,这个回调函数可能立即使用这个组件,或保存这个引用,将来再用(或者两者都做)。
|
||||
|
||||
使用ES6的箭头函数,为从`render` 中返回的东西添加一个`ref` 属性非常简单:
|
||||
|
||||
```html
|
||||
render: function() {
|
||||
return <TextInput ref={(c) => this._input = c} />;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this._input.focus();
|
||||
},
|
||||
```
|
||||
|
||||
或
|
||||
|
||||
```html
|
||||
render: function() {
|
||||
return (
|
||||
<TextInput
|
||||
ref={function(input) {
|
||||
if (input != null) {
|
||||
input.focus();
|
||||
}
|
||||
}} />
|
||||
);
|
||||
},
|
||||
```
|
||||
|
||||
注意当引用的组件被卸载以及无论何时这个引用改变之后,旧的引用将会被用`null` 作为一个参数来调用。这避免了当实例被存储的情形下- 像第一个例子那样 - 引起的内存泄漏。注意像这个例子中这样,用inline 函数表达式写引用的时候,每次有更新的时候Reac看到的都是不同的函数对象,在引用被组件的实例调用之前,引用被用`null` 调用。
|
||||
|
||||
## 完整的例子
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
// 清空input
|
||||
this.setState({userInput: ''}, function() {
|
||||
// 当这个组件被再次渲染之后,这个代码执行
|
||||
this.refs.theInput.focus(); //获取焦点了!
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click to Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
ref="theInput"
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
在这个例子中,我们的render函数返回了`<input />` 实例的一个描述。但是真的实例通过`this.refs.theInput` 访问。只要`ref="theInput"` 从`render` 中返回了, `this.refs.theInput` 就可以访问合适的实例。这个事件对于高级的(非DOM)的组件,例如`<Typeahead ref="myTypeahead" />` 也适用的。
|
||||
|
||||
|
||||
## 总结
|
||||
|
||||
在不方便通过Reactive的 `props` 和`state` 流的方式传递信息的时候,Refs是给一个特殊的子实例发送消息的重要的方法。然而,他们不应该成为你的应用程序的到哪里去的数据流的抽象。对于那些本质上来说非交互的情形来说,默认的,应该使用Reactive数据流而少用`ref` 。
|
||||
|
||||
### 优点:
|
||||
|
||||
- 在你的组件类中你可以定义任意的公开方法(例如在一个Typeahead定义一个reset方法),然后通过refs来调用这些方法(像这样`this.refs.myTypeahead.reset()`)。
|
||||
|
||||
- 执行 DOM操作,总是要求诸如`<input />` 这样的一个“原生”组件,并通过`this.refs.myInput` 来访问她的低层的MOD 节点。Refs是可以做成这个事的唯一的实践可行的方法。
|
||||
|
||||
- Refs自动管理!如果孩子被销毁了,它的ref也被销毁。在这里不用担心内存(除非你做了一些疯狂的事情来自己保持一个引用)。
|
||||
|
||||
### 小心:
|
||||
|
||||
- *绝对不要* 在组件的render方法内部- 获 当任何组件的render方法还在调用栈中执行的时候,访问refs 。
|
||||
- 如果你想要保护Google 闭包编译器崩溃的内力,确保绝不作为访问一个被特别的设置为一个字符串的属性。这就意味着,如果你用`ref="myRefString"` 来定义你的ref的话,你必须使用`this.refs['myRefsString']` 来访问。
|
||||
- 如果你不是用React做服务器编程的,在你的程序中,你首先的倾向是用refs来“让事情发生“。如果这是正是你的情况的话,花点时间,仔细的想想`state` 在这个组件的结构层次中应在在哪里使用。通常,正确的"拥有" 状态的地方是结构层次的高层。把状态放在那些地方通常可以消除使用`ref` 来”让事情发生” 的渴望 - 相反的,数据流通常能完成你的目标。
|
||||
@@ -144,4 +144,4 @@ Reactは `render()` からの出力であるコンポーネントであれば何
|
||||
|
||||
- *決して* コンポーネントのレンダリングメソッドの中の参照にアクセスしてはいけません。たとえコンポーネントのレンダリングメソッドのいずれかがコールスタックの中のどこかで動いているとしても。
|
||||
- もしGoogle Closure Compilerのクラッシュからの回復を守りたいなら、文字列として指定されたプロパティとしてアクセスしてはいけないことに気をつけてください。これは、 `ref="myRefString"` として参照が定義されている場合は、 `this.refs['myRefString']` を使ってアクセスしなければいけないことを意味します。
|
||||
- まだReactでプログラムを書いたことがない場合は、アプリケーションで「何かを起こす」ために参照を使おうとするでしょう。もしそのケースだった場合は、時間をかけて `state` がコンポーネントの階層のどこで保持されるべきか批評的に考えてください。多くの場合は、そのstateを「保持する」ための固有の場所が階層の高いレベルにあることがクリアになります。そのstateをその場所に配置することはよく「何かを起こす」ために `ref` を使うための願望を排除します。代わりに、データフローは普通、目標を達成します。
|
||||
- まだReactでプログラムを書いたことがない場合は、アプリケーションで「何かを起こす」ために参照を使おうとするでしょう。もしそのケースだった場合は、時間をかけて `state` がコンポーネントの階層のどこで保持されるべきか批評的に考えてください。多くの場合は、そのstateを「保持する」ための固有の場所が階層の高いレベルにあることがクリアになります。そのstateをその場所に配置することはよく「何かを起こす」ために `ref` を使うための願望を排除します。代わりに、データフローは普通、目標を達成します。
|
||||
|
||||
@@ -1,137 +1,125 @@
|
||||
---
|
||||
id: more-about-refs-ko-KR
|
||||
title: refs 심화
|
||||
title: refs에서 컴포넌트로
|
||||
permalink: more-about-refs-ko-KR.html
|
||||
prev: working-with-the-browser-ko-KR.html
|
||||
next: tooling-integration-ko-KR.html
|
||||
---
|
||||
render 메소드를 통해 UI 구조를 얻은 다음, 반환된 컴포넌트 인스턴스에 접근하거나 메소드를 호출할 방법이 필요할 수도 있습니다. 반응적 데이터 플로우가 `render()`의 결과물에서 최신의 `props`가 각각의 자식으로 보내진 것을 항상 보장하기 때문에 애플리케이션의 데이터 플로우를 만드는데 대체로 이런 작업은 필요가 없지만, 여전히 이런 작업이 필요하거나 유리한 경우가 있긴 합니다.
|
||||
컴포넌트를 빌드한 후에는 `render()`에서 반환된 컴포넌트 인스턴스에 접근하거나 메소드를 호출할 방법이 필요할 수도 있습니다. 반응적 데이터 플로우가 `render()`의 결과물에서 최신의 `props`가 각각의 자식으로 보내진 것을 항상 보장하기 때문에 애플리케이션의 데이터 플로우를 만드는데 대체로 이런 작업은 필요가 없지만, 여전히 이런 작업이 필요하거나 유리한 경우가 있긴 합니다. React는 이를 위해 `refs`라는 탈출구를 제공합니다. `refs`(레퍼런스)는 특히 다음과 같은 경우 유용합니다: 컴포넌트에 의해 렌더된 DOM 마크업을 찾을때 (인스턴스내의 절대적인 위치), 큰 프로젝트의 일부에 React 컴포넌트를 사용하는 경우 또는 기존의 코드베이스를 React로 변경하는 경우.
|
||||
|
||||
ref를 어떻게 얻는지 살펴보고, 예제를 완성해 봅시다.
|
||||
|
||||
인스턴스의 하위 계층구조에 존재하는 `<input />` 엘리먼트의 value를 빈 문자열(`''`)로 업데이트한 후 포커스 하는 경우를 생각해 봅시다.
|
||||
## ReactDOM.render에서 반환된 ref
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
this.setState({userInput: ''}); // 입력내용을 지워줍니다
|
||||
// 이제 <input />에 포커스를 주길 원합니다!
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
클릭해서 초기화하고 포커스주기
|
||||
</div>
|
||||
<input
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
컴포넌트에서 정의한, 가상의 DOM 엘리먼트를 반환하는 `render()`와 헷갈리지 않도록 합니다. [ReactDOM.render()](/react/docs/top-level-api-ko-KR.html#reactdom.render)는 컴포넌트의 **지원 인스턴스(backing instance)**에 대한 참조를 반환 합니다. [상태를 가지지 않는 컴포넌트](/react/docs/reusable-components-ko-KR.html#stateless-functions)에 대해선 `null`을 반환하죠.
|
||||
|
||||
|
||||
```js
|
||||
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
|
||||
```
|
||||
|
||||
명심하세요. 위의 코드는 컴포넌트 인스턴스를 반환하지 않습니다! 이는 그저 **ReactElement**:React에 마운트된 컴포넌트가 어떻게 보여야 할지 알려주는 경량의 표상(representation) 입니다.
|
||||
|
||||
```js
|
||||
var myComponentElement = <MyComponent />; // 이건 그냥 ReactElement 입니다.
|
||||
|
||||
한번 살펴보죠. 이 예제에서 우리는 시간이 지남에 따라 props에서 추론할 수 없는 무언가를 입력하도록 "알려주길" 원했습니다. 이 사례에서 우리는 이제 포커스 되도록 "알려주길" 원합니다. 그러나 몇 가지 문제가 있습니다. `render()`에서 반환된 것은 "자식" 컴포넌트의 실제 구성이 아니고, 단지 특정 시점의 인스턴스의 자식에 대한 *서술*일 뿐입니다. - 말하자면 스냅샷인 것이지요.
|
||||
// 여기 코드가 위치합니다...
|
||||
|
||||
var myComponentInstance = ReactDOM.render(myComponentElement, myContainer);
|
||||
myComponentInstance.doSomething();
|
||||
```
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 기억하세요, `render()`에서 반환된 것은 *실제* 자식 인스턴스가 아닙니다. 단지 특정 시점의 컴포넌트의 하위 계층구조에 있는 자식 인스턴스의 *서술*일 뿐입니다.
|
||||
> 이는 오직 최상위 레벨에서만 사용되어야 합니다. 컴포넌트의 내부에서는 `props`와 `state`가 자식 컴포넌트와 통신하도록 하거나 문자열이나 콜백 어트리뷰트 등 ref를 얻어오는 다른 방법을 사용하도록 하세요.
|
||||
|
||||
## ref 콜백 어트리뷰트
|
||||
|
||||
React는 어떤 컴포넌트에든 추가할 수 있는 특별한 어트리뷰트를 제공합니다. `ref` 어트리뷰트는 콜백 함수일 수 있으며 이는 컴포넌트가 마운트 된 후 즉시 실행됩니다. 참조된 컴포넌트는 파라미터로 전달될 것이며 콜백 함수는 즉시, 혹은 미래에 사용하기 위해 컴포넌트의 참조를 저장합니다.
|
||||
|
||||
이는 `render()`에서 반환된 무언가를 "계속 유지할 수" 없으며 아무런 의미도 없을 것이라는 뜻입니다.
|
||||
`render`에서 반환되는 무엇에든 `ref` 어트리뷰트를 추가하는 것은 간단합니다:
|
||||
|
||||
```javascript
|
||||
// 안티패턴: 이것은 동작하지 않습니다.
|
||||
```js
|
||||
render: function() {
|
||||
var myInput = <input />; // 여기서 메소드를 호출할 겁니다.
|
||||
this.rememberThisInput = myInput; // 언젠가 미래의 특정 시점에 입력할 거에요! YAY!
|
||||
return (
|
||||
<div>
|
||||
<div>...</div>
|
||||
{myInput}
|
||||
</div>
|
||||
<TextInput
|
||||
ref={function(input) {
|
||||
if (input != null) {
|
||||
input.focus();
|
||||
}
|
||||
}} />
|
||||
);
|
||||
}
|
||||
},
|
||||
```
|
||||
ES6 화살표 함수를 사용한다면 다음과 같습니다:
|
||||
|
||||
```js
|
||||
render: function() {
|
||||
return <TextInput ref={(c) => this._input = c} />;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this._input.focus();
|
||||
},
|
||||
```
|
||||
|
||||
이 예제에서 `<input />`은 단지 `<input />`의 *서술*일 뿐입니다. 이 서술은 `<input />`에 대한 *진짜* **지원 인스턴스(backing instance)**를 생성하는 데 사용됩니다.
|
||||
`<div />` 같은 DOM 컴포넌트에 ref를 추가하면 DOM 노드를 얻게 됩니다; `<TextInput />` 같은 합성 컴포넌트에 ref를 추가하면 React 클래스 인스턴스를 얻게 됩니다. 후자의 경우, 클래스에 정의되어 있는 노출된 메소드를 호출할 수 있습니다.
|
||||
|
||||
자 그럼 어떻게 *진짜* input의 지원 인스턴스를 다룰까요?
|
||||
참조된 컴포넌트가 언마운트되고 ref가 변경되면 이전의 ref는 `null`을 인수로 호출됨을 주의 하세요. 이는 첫번째 예제에서처럼 인스턴트가 저장된 경우의 메모리 누수를 방지합니다. 또한 예제와 같이 ref를 인라인 함수 표현식으로 서술하게되면 React는 모든 업데이트에 대해 다른 함수 객체를 참조하게 됩니다. ref는 컴포넌트의 인스턴스의 호출 이전에 `null` 객체와 함께 즉시 호출될 것입니다.
|
||||
|
||||
## ref 문자열 어트리뷰트
|
||||
|
||||
React는 `render()`로 출력된 컴포넌트에 추가할 수 있는 아주 특별한 프로퍼티를 지원합니다. 이 특별한 프로퍼티는 `render()`에서 반환한 모든 것들에 대해 각각에 대응하는 **지원 인스턴스**를 참조할 수 있습니다. 이는 항상 어떤 시점에서든 올바른 인스턴스를 보장합니다.
|
||||
React는 ref에 콜백 대신 문자열도 지원합니다 이런 접근은 이제 과거의 것이긴 합니다.
|
||||
|
||||
|
||||
간단합니다:
|
||||
|
||||
1. `render`에서 반환된 값을 `ref` 어트리뷰트에 할당합니다:
|
||||
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
|
||||
2. 다른 코드(일반적으로는 이벤트 핸들러 코드)에서 `this.refs`를 통해 **지원 인스턴스**에 접근 합니다:
|
||||
|
||||
```javascript
|
||||
this.refs.myInput
|
||||
```
|
||||
```javascript
|
||||
var input = this.refs.myInput;
|
||||
var inputValue = input.value;
|
||||
var inputRect = input.getBoundingClientRect();
|
||||
```
|
||||
|
||||
`this.refs.myInput`를 호출해 컴포넌트의 DOM 노드에 접근할 수 있습니다.
|
||||
|
||||
## ref 콜백 어트리뷰트
|
||||
|
||||
`ref` 어트리뷰트는 이름 대신 콜백 함수가 될 수도 있습니다. 이 콜백은 컴포넌트가 마운트 된 뒤 즉시 실행될 것입니다. 참조된 컴포넌트는 매개 변수로 전달되며 콜백은 이를 즉시 사용하거나, 앞으로 사용하기 위해 참조를 저장해 놓거나, 혹은 둘 다 할 것입니다.
|
||||
|
||||
`render`에서 반환한 모든 것에 간단하게 `ref` 어트리뷰트를 할당할 수 있습니다:
|
||||
|
||||
```html
|
||||
<input ref={ function(component){component.focus();} } />
|
||||
```
|
||||
|
||||
## 예제 완성하기
|
||||
## 최종 예제
|
||||
React 컴포넌트의 참조를 얻기 위해서, 현재의 React 컴포넌트를 위해서는 `this`를, 소유한 컴포넌트에 대해서는 ref를 사용할 수 있습니다. 다음과 같이 작동 합니다:
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
// input을 비워준다
|
||||
this.setState({userInput: ''}, function() {
|
||||
// 이 코드는 컴포넌트가 다시 렌더 된 다음 실행됩니다
|
||||
this.refs.theInput.focus(); // 짠! 포커스 됨!
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
클릭해서 초기화하고 포커스주기
|
||||
</div>
|
||||
<input
|
||||
ref="theInput"
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// 명시적으로 텍스트 인풋에 포커스하기 위해 raw DOM API를 사용합니다.
|
||||
this.myTextInput.focus();
|
||||
},
|
||||
render: function() {
|
||||
// ref 어트리뷰트는 컴포넌트가 마운트되면
|
||||
// this.refs에 컴포넌트에 대한 참조를 추가합니다.
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref={(ref) => this.myTextInput = ref} />
|
||||
<input
|
||||
type="button"
|
||||
value="Focus the text input"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<MyComponent />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
이 예제에서 render 함수는 `<input />` 인스턴스의 서술을 반환했지만, 진짜 인스턴스는 `this.refs.theInput`을 통해 접근할 수 있었습니다. `render`에서 `ref="theInput"`을 가진 컴포넌트가 반환된 동안, `this.refs.theInput`은 적절한 인스턴스에 접근합니다. 이는 `<Typeahead ref="myTypeahead" />`처럼 DOM이 아닌 고수준의 컴포넌트에서도 동작합니다.
|
||||
이 예제에서, 텍스트 인풋의 **지원 인스턴스**에 대한 참조를 얻었으며 버튼이 클릭되었을때 `focus()`를 호출했습니다.
|
||||
|
||||
합성 컴포넌트에서는 참조는 컴포넌트 클래스의 인스턴스를 가리키기 때문에 클래스에 정의된 어떤 메소드도 호출할 수 있습니다. 컴포넌트의 기저에 있는 DOM 노드에 접근하기 위해서는 [ReactDOM.findDOMNode](/react/docs/top-level-api-ko-KR.html#reactdom.finddomnode)를 "탈출구"로 사용할 수 있습니다. 하지만 이는 캡슐화를 깨며, 대부분의 경우 React 모델을 이용해 더 명확한 방법으로 구조를 짤 수 있기 때문에 추천하지 않습니다.
|
||||
|
||||
|
||||
## 요약
|
||||
|
||||
@@ -139,12 +127,13 @@ Refs는 반응적인 `props`와 `state` 스트리밍을 통해서는 불편했
|
||||
|
||||
### 이점:
|
||||
|
||||
- 컴포넌트 클래스에 public 메소드(ex. Typeahead의 reset)를 선언할 수 있으며 refs를 통해 그를 호출할 수 있습니다. (ex. `this.refs.myTypeahead.reset()`)
|
||||
- DOM을 측정하기 위해서는 거의 항상 `<input />` 같은 "기본" 컴포넌트를 다루고 `this.refs.myInput`를 통해 그 기저의 DOM 노드에 접근해야 합니다. Refs는 이 일을 확실하게 수행하는 몇 안 되는 실용적인 방법의 하나입니다.
|
||||
- 컴포넌트 클래스에 public 메소드(ex. Typeahead의 reset)를 선언할 수 있으며 refs를 통해 그를 호출할 수 있습니다. (ex. `this.refs.myTypeahead.reset()`) 대부분, 이는 선언적으로 refs를 사용하는 것보다 내장 React 데이터 흐름을 명확하게 합니다.
|
||||
- DOM을 측정하기 위해서는 거의 항상 `<input />` 같은 "기본" 컴포넌트를 다루고 ref를 통해 그 기저의 DOM 노드에 접근해야 합니다. Refs는 이 일을 확실하게 수행하는 몇 안 되는 실용적인 방법의 하나입니다.
|
||||
- Refs는 자동으로 관리합니다! 자식이 파괴되면, 그의 ref도 마찬가지로 파괴됩니다. 참조를 유지하기 위해 뭔가 미친 짓을 하지 않는 한, 메모리 걱정은 하지 않아도 됩니다.
|
||||
|
||||
### 주의:
|
||||
|
||||
- 컴포넌트의 렌더 메소드에서는, 혹은 컴포넌트의 렌더 메소드가 콜스택 어디에서든 실행되는 동안에는 절대 접근하지 마세요.
|
||||
- Google Closure Compiler에서의 분쇄 복원력 유지(to preserve Crushing resilience)를 위해서는 문자열로 정의한 것을 절대 프로퍼티로 접근하지 마세요. ref가 ref="myRefString"으로 정의되어 있다면 this.refs['myRefString']으로만 접근해야 한다는 이야기 입니다.
|
||||
- Google Closure Compiler에서의 어드벤스드 모드 분쇄 복원력 유지(to preserve advanced-mode crushing resilience)를 위해서는 문자열로 정의한 것을 절대 프로퍼티로 접근하지 마세요. ref가 ref="myRefString"으로 정의되어 있다면 this.refs['myRefString']으로만 접근해야 한다는 이야기 입니다.
|
||||
- React로 앱을 여럿 만들어 본 경험이 없다면, 보통은 처음엔 앱에서 "무언가 일어나도록" 하는데 refs를 사용하게 될 것입니다. 이 경우, 잠시 시간을 내어 `state`가 컴포넌트 계층구조의 어느 부분에서 관리되어야 할지 비판적으로 생각해 봅시다. 대개는 state가 계층구조의 더 높은 레벨에서 "소유"하는 것이 타당함이 명확해집니다. 그렇게 함으로써 `ref`를 사용해 "무언가 일어나도록" 하려는 욕망이 대부분 제거됩니다. - 대신에 데이터 플로우를 통해 대개 원하는 바를 달성하게 될 것입니다.
|
||||
- Refs는 [상태를 가지지 않는 함수](/react/docs/reusable-components-ko-KR.html#stateless-functions)에 붙일 수 없습니다. 왜냐하면 컴포넌트가 내부 인스턴스를 가지지 않기 때문입니다. 상태를 가지지 않는 컴포넌트는 항상 일반 컴포넌트로 감싸 ref를 조합 컴포넌트에 붙일 수 있습니다.
|
||||
|
||||
@@ -5,7 +5,7 @@ permalink: more-about-refs.html
|
||||
prev: working-with-the-browser.html
|
||||
next: tooling-integration.html
|
||||
---
|
||||
After building your component, you may find yourself wanting to "reach out" and invoke methods on component instances returned from `render()`. In most cases, this should be unnecessary because the reactive data flow always ensures that the most recent props are sent to each child that is output from render(). However, there are a few cases where it still might be necessary or beneficial, so React provides an escape hatch known as `refs`. These `refs` (references) are especially useful when you need to: find the DOM markup rendered by a component (for instance, to position it absolutely), use React components in a larger non-React application, or transition your existing codebase to React.
|
||||
After building your component, you may find yourself wanting to "reach out" and invoke methods on component instances returned from `render()`. In most cases, this should be unnecessary because the reactive data flow always ensures that the most recent props are sent to each child that is output from `render()`. However, there are a few cases where it still might be necessary or beneficial, so React provides an escape hatch known as `refs`. These `refs` (references) are especially useful when you need to: find the DOM markup rendered by a component (for instance, to position it absolutely), use React components in a larger non-React application, or transition your existing codebase to React.
|
||||
|
||||
Let's look at how to get a ref, and then dive into a complete example.
|
||||
|
||||
@@ -33,7 +33,6 @@ myComponentInstance.doSomething();
|
||||
>
|
||||
> This should only ever be used at the top level. Inside components, let your `props` and `state` handle communication with child components, or use one of the other methods of getting a ref (string attribute or callbacks).
|
||||
|
||||
|
||||
## The ref Callback Attribute
|
||||
|
||||
React supports a special attribute that you can attach to any component. The `ref` attribute can be a callback function, and this callback will be executed immediately after the component is mounted. The referenced component will be passed in as a parameter, and the callback function may use the component immediately, or save the reference for future use (or both).
|
||||
@@ -67,7 +66,6 @@ When attaching a ref to a DOM component like `<div />`, you get the DOM node bac
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## The ref String Attribute
|
||||
|
||||
React also supports using a string (instead of a callback) as a ref prop on any component, although this approach is mostly legacy at this point.
|
||||
@@ -86,7 +84,6 @@ React also supports using a string (instead of a callback) as a ref prop on any
|
||||
var inputRect = input.getBoundingClientRect();
|
||||
```
|
||||
|
||||
|
||||
## A Complete Example
|
||||
In order to get a reference to a React component, you can either use `this` to get the current React component, or you can use a ref to get a reference to a component you own. They work like this:
|
||||
|
||||
@@ -94,11 +91,13 @@ In order to get a reference to a React component, you can either use `this` to g
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// Explicitly focus the text input using the raw DOM API.
|
||||
this.myTextInput.focus();
|
||||
if (this.myTextInput !== null) {
|
||||
this.myTextInput.focus();
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
// The ref attribute adds a reference to the component to
|
||||
// this.refs when the component is mounted.
|
||||
// The ref attribute is a callback that saves a reference to the
|
||||
// component to this.myTextInput when the component is mounted.
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref={(ref) => this.myTextInput = ref} />
|
||||
@@ -134,7 +133,7 @@ Refs are a great way to send a message to a particular child instance in a way t
|
||||
|
||||
### Cautions:
|
||||
|
||||
- *Never* access refs inside of any component's render method - or while any component's render method is even running anywhere in the call stack.
|
||||
- *Never* access refs inside of any component's render method – or while any component's render method is even running anywhere in the call stack.
|
||||
- If you want to preserve Google Closure Compiler advanced-mode crushing resilience, make sure to never access as a property what was specified as a string. This means you must access using `this.refs['myRefString']` if your ref was defined as `ref="myRefString"`.
|
||||
- If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where `state` should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use `ref`s to "make things happen" – instead, the data flow will usually accomplish your goal.
|
||||
- If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use `ref`s to "make things happen" – instead, the data flow will usually accomplish your goal.
|
||||
- Refs may not be attached to a [stateless function](/react/docs/reusable-components.html#stateless-functions), because the component does not have a backing instance. You can always wrap a stateless component in a standard composite component and attach a ref to the composite component.
|
||||
|
||||
@@ -1,109 +1,45 @@
|
||||
---
|
||||
id: more-about-refs-zh-CN
|
||||
title: 关于Refs的更多内容
|
||||
title: 对组件的refs
|
||||
permalink: more-about-refs-zh-CN.html
|
||||
prev: working-with-the-browser-zh-CN.html
|
||||
next: tooling-integration-zh-CN.html
|
||||
---
|
||||
从render方法返回你的UI结构以后,你也许发现自己想“接触”并且调用从 `render()`返回的组件实例上的方法。通常,这样做对于让数据流过你的应用并不是必须的,因为Reactive的数据流总是确保最新的`props` 被发送到 `render()`输出的每个子级。然而,有一些情况下它仍旧是必要或者有益的。
|
||||
在建立你的组件以后,你也许发现你想“接触”并且调用从 `render()`返回的组件实例上的方法。大部分情况下,这是不必要的因为响应式的数据流总是确保最近的 props 被送到每一个从 `render()` 输出的子级。然而,有一些情况下它仍旧是必要或者有益的,所以 React 提供了一个被称为 `refs` 的安全舱口。这些 `refs` (引用) 在你需要时特别有用 如:查找被组件绘制的 DOM 标记(例如,绝对定位它),使用 React 组件在一个大的非React组件里,或者转换你已有的代码库到React。
|
||||
|
||||
考虑这样一种场景,当你想要告诉一个`<input />` 元素(存在于你的实例的子层级)在你更新他的值为空字符串后获得焦点。
|
||||
让我们来看看怎样取得一个ref,然后深入完整的例子。
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
this.setState({userInput: ''}); // Clear the input
|
||||
// We wish to focus the <input /> now!
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click to Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
## 从 ReactDOM.render 返回的 ref
|
||||
|
||||
不要被 你在你的组件(它返回一个虚拟的DOM元素)里定义的 `render()` 迷惑了, [ReactDOM.render()](/react/docs/top-level-api.html#reactdom.render) 会返回一个对你的组件的 **backing instance** 的引用(或者 `null` for [stateless components](/react/docs/reusable-components.html#stateless-functions)).
|
||||
|
||||
|
||||
```js
|
||||
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
|
||||
```
|
||||
|
||||
记住,不管怎样,JSX不会返回一个组件的实例!它只是一个 **ReactElement**: 一个轻量级的表达,告诉React被挂载的组件应该长什么样。
|
||||
|
||||
注意,在这个例子中,我们想 "告诉" input 一些东西 - 那些最后它不能从他的props推断出来的东西。在这个场景中我们想 "告诉" 它,它应该转为获得焦点。然而,有一些挑战。从`render()` 返回的东西不是你实际的 "子" 组件的组合,而是一个在某刻特定实例的子组件的 *描述* - 一个快照。
|
||||
```js
|
||||
var myComponentElement = <MyComponent />; // 这只是一个 ReactElement.
|
||||
|
||||
// 省略一些代码 ...
|
||||
|
||||
var myComponentInstance = ReactDOM.render(myComponentElement, myContainer);
|
||||
myComponentInstance.doSomething();
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 记住,从 `render()`返回的东西不是你的 *实际的* 被渲染出的子组件实例。从 `render()` 返回的东西仅仅是一个在特定时间你的组件的子层级中的子实例的 *描述*。
|
||||
> 这只应该用在顶层上。在组件内部,让你的 `props` 和 `state` 来处理和子组件的通信,或者使用其他获取ref的方法(string attribute or callbacks)。
|
||||
|
||||
## ref Callback 属性
|
||||
|
||||
这意味着你万万不要把你从`render()`返回的东西 "抓住不放" 然后期望它变成任何有意义的东西。
|
||||
React支持一种非常特殊的属性,你可以附加到任何的组件上。 `ref` 属性可以是一个回调函数,这个回调函数会在组件被挂载后立即执行。被引用的组件会被作为参数传递,回调函数可以用立即使用这个组件,或者保存引用以后使用(或者二者皆是)。
|
||||
|
||||
```javascript
|
||||
// 反面模式: 这行不通.
|
||||
render: function() {
|
||||
var myInput = <input />; // I'm going to try to call methods on this
|
||||
this.rememberThisInput = myInput; // input at some point in the future! YAY!
|
||||
return (
|
||||
<div>
|
||||
<div>...</div>
|
||||
{myInput}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
简单的说就是添加一个 `ref` 属性到任何从 `render` 返回的东西上:
|
||||
|
||||
在这个例子中,`<input />` 仅仅是一个`<input />` 的 *描述*。 这个描述被用于为`<input />`创建一个 *真实的* **支持实例(backing instance)**
|
||||
|
||||
所以我们如何与input的 *真实的*支持实例对话?
|
||||
|
||||
## ref String 属性
|
||||
|
||||
React支持一种非常特殊的属性,你可以附加到任何从`render()`输出的组件上。这个特殊的属性允许你引用任何从`render()`返回的东西的对应 **支持实例(backing instance)** 。它总是保证是适当的实例,在任何时点上。
|
||||
|
||||
就是这么简单:
|
||||
|
||||
1. 赋值`ref`属性为任何从`render` 返回的东西,比如:
|
||||
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
|
||||
2. 在其他一些代码中(典型的事件处理代码),通过`this.refs`访问 **支持实例(backing instance)**,如:
|
||||
|
||||
```javascript
|
||||
this.refs.myInput
|
||||
```
|
||||
|
||||
你可以直接通过调用`ReactDOM.findDOMNode(this.refs.myInput)` 访问组件的DOM node。
|
||||
|
||||
|
||||
## ref 回调属性
|
||||
|
||||
`ref` 属性可以是一个回调函数而不是名字。这个回调函数将会在组件挂载以后立即执行。被引用的组件将被作为参数传递,并且回调函数可以立即使用组件,或者保存引用将来使用(或两者都是)。
|
||||
|
||||
通过使用ES6的箭头函数,它像添加一个`ref`属性到任何从`render`返回的东西一样简单。
|
||||
|
||||
```html
|
||||
render: function() {
|
||||
return <TextInput ref={(c) => this._input = c} />;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this._input.focus();
|
||||
},
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```html
|
||||
```js
|
||||
render: function() {
|
||||
return (
|
||||
<TextInput
|
||||
@@ -115,60 +51,87 @@ React支持一种非常特殊的属性,你可以附加到任何从`render()`
|
||||
);
|
||||
},
|
||||
```
|
||||
或者使用ES6的箭头函数:
|
||||
|
||||
```js
|
||||
render: function() {
|
||||
return <TextInput ref={(c) => this._input = c} />;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this._input.focus();
|
||||
},
|
||||
```
|
||||
|
||||
当连接一个ref到一个DOM组件如 `<div />`,你取回DOM节点;当连接一个ref到一个复合组件如 `<TextInput />`,你会得到React类的实例。在后一种情况下,你可以调用任何那个组件的类暴露的方法。
|
||||
|
||||
注意当被引用的组件卸载和每当ref变动,旧的ref将会被以`null`做参数调用。这阻止了在实例被保存的情况下的内存泄露,如第一个例子。注意当像在这里的例子,使用内联函数表达式写refs,React在每次更新都看到不同的函数对象,ref将会被以`null` 立即调用在它被以组件实例调用前。
|
||||
|
||||
## ref String 属性
|
||||
|
||||
## 完成的示例
|
||||
React同样支持使用一个字符串(代替回调函数)在任意组件上作为一个 ref prop,尽管这个方法在这点上主要是遗留物。
|
||||
|
||||
1. 赋值`ref`属性为任何从`render` 返回的东西,比如:
|
||||
|
||||
```html
|
||||
<input ref="myInput" />
|
||||
```
|
||||
|
||||
2. 在其他一些代码中(典型的事件处理代码),通过`this.refs`访问 **支持实例(backing instance)**,如:
|
||||
|
||||
```javascript
|
||||
var input = this.refs.myInput;
|
||||
var inputValue = input.value;
|
||||
var inputRect = input.getBoundingClientRect();
|
||||
```
|
||||
|
||||
## 完整的示例
|
||||
为了获取一个React组件的引用,你既可以使用 `this` 来获取当前的React组件,也可以使用一个 ref 来获取一个你拥有的组件的引用。他们像这样工作:
|
||||
|
||||
```javascript
|
||||
var App = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {userInput: ''};
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({userInput: e.target.value});
|
||||
},
|
||||
clearAndFocusInput: function() {
|
||||
// Clear the input
|
||||
this.setState({userInput: ''}, function() {
|
||||
// This code executes after the component is re-rendered
|
||||
ReactDOM.findDOMNode(this.refs.theInput).focus(); // Boom! Focused!
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div onClick={this.clearAndFocusInput}>
|
||||
Click to Focus and Reset
|
||||
</div>
|
||||
<input
|
||||
ref="theInput"
|
||||
value={this.state.userInput}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
var MyComponent = React.createClass({
|
||||
handleClick: function() {
|
||||
// Explicitly focus the text input using the raw DOM API.
|
||||
this.myTextInput.focus();
|
||||
},
|
||||
render: function() {
|
||||
// The ref attribute adds a reference to the component to
|
||||
// this.refs when the component is mounted.
|
||||
return (
|
||||
<div>
|
||||
<input type="text" ref={(ref) => this.myTextInput = ref} />
|
||||
<input
|
||||
type="button"
|
||||
value="Focus the text input"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<MyComponent />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
在这个例子中, 我们的render函数返回一个 `<input />` 实例的描述。但是真正的实例通过 `this.refs.theInput` 访问。只要带有`ref="theInput"`的子组件从 `render`被返回,`this.refs.theInput` 就可以访问正确的实例。这甚至在更高层(non-DOM)的组件上生效,比如`<Typeahead ref="myTypeahead" />`。
|
||||
在这个例子中,我们获得一个对 text input **backing instance** 的引用 并且当按钮被点击时我们调用 `focus()`。
|
||||
|
||||
对于复合组件,引用会指向一个组件类的实例所以你可以调用那个类定义的任何方法。如果你需要访问那个组件的底层的DOM节点,你可以使用 [ReactDOM.findDOMNode](/react/docs/top-level-api.html#reactdom.finddomnode) 作为一个 `安全舱口` 但是我们不推荐这样,因为它打破了封装,在大多数情况下都有一个清晰的方法来以React模式构建你的代码.
|
||||
|
||||
## 总结
|
||||
|
||||
Refs是一种很好的发送消息给特定子实例(通过流式的Reactive `props` 和 `state`来做会不方便)的方式。它们应该,不论怎样,不是你数据流通你的应用的首选。默认方式,使用Reactive数据流并为本身不是reactive的用例保存`ref`。
|
||||
Refs是一种很好的发送消息给特定子实例(通过流式的Reactive `props` 和 `state`来做会不方便)的方式。它们应该,不论怎样,不是你数据流通你的应用的首选。默认情况下,使用响应式数据流,并为本身不是reactive的用例保存`ref`s。
|
||||
|
||||
### 优点:
|
||||
|
||||
- 你可以在你的组件类里定义任何的公开方法(比如在一个Typeahead的重置方法)然后通过refs调用那些公开方法(比如`this.refs.myTypeahead.reset()`)。
|
||||
- 实行DOM测量几乎总是需要接触到"原生" 组件比如 `<input />` 并且`ReactDOM.findDOMNode(this.refs.myInput)`通过访问它的底层DOM 节点。 Refs 是唯一一个可靠的完成这件事的实际方式。
|
||||
- 你可以在你的组件类里定义任何的公开方法(比如在一个Typeahead的重置方法)然后通过refs调用那些公开方法(比如`this.refs.myTypeahead.reset()`)。在大多数情况下,使用内建的React数据流更清晰,而不是使用强制的ref。
|
||||
- 实行DOM测量几乎总是需要接触到 "原生" 组件比如 `<input />` 并且通过 ref 访问它的底层DOM节点。 Refs 是唯一一个可靠的完成这件事的实际方式。
|
||||
- Refs 是为你自动管理的!如果子级被销毁了,它的ref也同样为你销毁了。这里不用担心内存(除非你做了一些疯狂的事情来自己保持一份引用)。
|
||||
|
||||
### 注意事项:
|
||||
|
||||
- *绝不* 在任何组件的 render 方法中访问 refs - 或者当任何组件的render方法还在调用栈上的任何地方运行时。
|
||||
- 如果你想要保留Google Closure Compiler Crushing resilience,务必不要把指明为字符串的以属性来访问。这意味这你必须用`this.refs['myRefString']`访问,如果你的ref被定义为`ref="myRefString"`。
|
||||
- 如果你没有用React写过数个程序,你的第一反应通常是打算试着用refs来在你的应用里"让事情发生"。如果是这样,花一些时间并且更精密的思考`state`应该属于组件层级的哪个位置。常常,这会变得清晰:正确的"拥有"那个属性的地方应该在层级的更高层上。把state放在那里往往消除了任何使用`ref`来 "让事情发生"的渴望 - 作为替代,数据流通常将完成你的目录。
|
||||
|
||||
- 如果你想要保留Google Closure Compiler advanced-mode crushing resilience,务必不要以属性的方式访问指明为字符串的属性。这意味这你必须用`this.refs['myRefString']`访问,如果你的ref被定义为`ref="myRefString"`。
|
||||
- 如果你没有用React写过数个程序,你的第一反应通常是打算试着用refs来在你的应用里"让事情发生"。如果是这样,花一些时间并且更精密的思考`state`应该属于组件层级的哪个位置。常常,这会变得清晰:正确的"拥有"那个属性的地方应该在层级的更高层上。把state放在那里 往往消除了任何使用`ref`s 来 "让事情发生"的渴望 - 作为替代,数据流通常将完成你的目标。
|
||||
- Refs 不能连接到一个 [stateless function(无状态函数)](/react/docs/reusable-components.html#stateless-functions),因为这些组件没有支持实例。你总是可以包装一个无状态组件在一个标准复合组件里并且连接一个ref到这个复合组件。
|
||||
|
||||
@@ -38,4 +38,4 @@ JSXを使用したい場合、[ダウンロードページに](/react/downloads.
|
||||
|
||||
### 役に立つオープンソースのプロジェクト
|
||||
|
||||
オープンソースコミュニティがJSXをいくつかのエディタやビルドシステムで使用するためのツールを作成しました。一覧は[JSXのインテグレーション](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations)を参照してください。
|
||||
オープンソースコミュニティがJSXをいくつかのエディタやビルドシステムで使用するためのツールを作成しました。一覧は[JSXのインテグレーション](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations)を参照してください。
|
||||
|
||||
@@ -23,7 +23,7 @@ next: addons-ko-KR.html
|
||||
|
||||
### 브라우저에서 JSX 변환
|
||||
|
||||
JSX를 사용하신다면, [다운로드 페이지](/react/downloads.html)에서 브라우저 JSX 변환기를 제공합니다. 간단히 `<script type="text/jsx">`를 넣으면 JSX 변환기가 작동합니다.
|
||||
JSX를 사용하신다면, Babel에서 browser.js라는 [개발용 브라우저 ES6, JSX 변환기](http://babeljs.io/docs/usage/browser/)를 제공합니다. 이는 `babel-core`의 npm 릴리스나 [CDNJS](http://cdnjs.com/libraries/babel-core)로 넣을 수 있습니다. `<script type="text/babel">`를 넣으면 JSX 변환기가 작동합니다.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
@@ -32,12 +32,48 @@ JSX를 사용하신다면, [다운로드 페이지](/react/downloads.html)에서
|
||||
|
||||
### 상용화하기: 미리 컴파일된 JSX
|
||||
|
||||
[npm](https://www.npmjs.com/) 모듈을 가지고 있다면, 간단히 `npm install -g react-tools`를 실행해 커맨드 라인 `jsx` 툴을 설치할 수 있습니다. 이 툴은 JSX 구문을 일반적인 JavaScript파일로 변환해 브라우져에서 바로 실행할 수 있도록 합니다. 디렉터리를 감시해 파일이 변경되었을 때 자동으로 변환하도록 할 수도 있습니다. 예를 들면 `jsx --watch src/ build/` 이렇게요.
|
||||
[npm](https://www.npmjs.com/) 모듈을 가지고 있다면, `npm install -g babel-cli`를 실행할 수 있습니다. Babel은 React v0.12이상을 내장 지원합니다. 태그는 자동적으로 동등한 `React.createElement(...)`로 변환되며, `displayName`은 모든 `React.createClass` 호출에 자동으로 추론, 추가됩니다.
|
||||
|
||||
기본적으로는 JSX 파일들은 `.js` 확장자로 변환됩니다. `jsx --extension jsx src/ build/`를 사용해 `.jsx` 확장자로 파일들을 변환할 수 있습니다.
|
||||
이 툴은 JSX 구문을 일반적인 JavaScript파일로 변환해 브라우져에서 바로 실행할 수 있도록 합니다. 디렉터리를 감시해 파일이 변경되었을 때 자동으로 변환하도록 할 수도 있습니다. 예를 들면 `babel --watch src/ --out-dir lib/` 이렇게요.
|
||||
|
||||
이 툴을 어떻게 사용하는지 더 자세하게 알고싶으시면 `jsx --help`를 실행해 보세요.
|
||||
Babel 6부터 기본값으로 변환기가 포함되지 않게 되었습니다. 이는 `babel` 명령을 실행할 때나 `.babelrc`에 반드시 옵션을 지정해야 한다는 뜻입니다. React를 사용할 때 가장 일반적인 방법은 `es2015`, `react` 프리셋을 사용하는 것입니다. Babel의 변경에 대한 좀 더 자세한 정보는 [블로그에 올라온 Babel 6 공지 글](http://babeljs.io/blog/2015/10/29/6.0.0/)을 읽어보세요.
|
||||
|
||||
ES2015 문법과 React를 사용하려 할 경우의 예제입니다.
|
||||
|
||||
```
|
||||
npm install babel-preset-es2015 babel-preset-react
|
||||
babel --presets es2015,react --watch src/ --out-dir lib/
|
||||
```
|
||||
|
||||
기본적으로는 JSX 파일들은 `.js` 확장자로 변환됩니다. 바벨을 어떻게 사용하는지 더 자세하게 알고싶으시면 `babel --help`를 실행해 보세요.
|
||||
|
||||
출력 예:
|
||||
|
||||
```
|
||||
$ 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);
|
||||
```
|
||||
|
||||
### 도움되는 오픈소스 프로젝트들
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ Every project uses a different system for building and deploying JavaScript. We'
|
||||
|
||||
### CDN-hosted React
|
||||
|
||||
We provide CDN-hosted versions of React [on our download page](/react/downloads.html). These prebuilt files use the UMD module format. Dropping them in with a simple `<script>` tag will inject a `React` global into your environment. It should also work out-of-the-box in CommonJS and AMD environments.
|
||||
|
||||
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
|
||||
|
||||
@@ -23,19 +22,27 @@ We have instructions for building from `master` [in our GitHub repository](https
|
||||
|
||||
### In-browser JSX Transform
|
||||
|
||||
If you like using JSX, Babel provides an [in-browser ES6 and JSX transformer for development](http://babeljs.io/docs/usage/browser/) called browser.js that can be included from a `babel-core` npm release or from [CDNJS](http://cdnjs.com/libraries/babel-core). Include a `<script type="text/babel">` tag to engage the JSX transformer.
|
||||
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`. Babel has built-in support for React v0.12 and v0.13. Tags are automatically transformed to their equivalent `React.createElement(...)`, `displayName` is automatically inferred and added to all React.createClass calls.
|
||||
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:
|
||||
@@ -68,7 +75,6 @@ var HelloMessage = React.createClass({
|
||||
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.
|
||||
|
||||
@@ -14,7 +14,6 @@ next: addons-zh-CN.html
|
||||
|
||||
我们提供了CDN-hosted版本的React[在我们的下载页面](/react/downloads.html).这些预构建的文件使用UMD模块格式。将他们放进一个简单的`<script>` 标签将会注入一个`React` 全局变量到你的环境里。这也同样在CommonJS 和 AMD 环境里开箱即用。
|
||||
|
||||
|
||||
### 使用 master
|
||||
|
||||
我们[在我们的 GitHub repository](https://github.com/facebook/react)有从`master`构建的说明。我们在`build/modules` 下构建了一个CommonJS模块的树,你可以把它放到任何支持CommonJS的环境或者打包工具里。
|
||||
@@ -23,19 +22,27 @@ next: addons-zh-CN.html
|
||||
|
||||
### 浏览器中的JSX转化
|
||||
|
||||
如果你喜欢使用JSX,Babel提供了一个被称为browser.js的[开发用的浏览器中的 ES6 和 JSX 转换器](http://babeljs.io/docs/usage/browser/) ,它可以从`babel-core` npm release 或者[CDNJS](http://cdnjs.com/libraries/babel-core) 中 include。Include `<script type="text/babel">` 标记来使用 JSX 转换器.
|
||||
如果你喜欢使用JSX,Babel5 提供了被称为browser.js 用于开发的一个浏览器内的 ES6 和 JSX 转换器,它可以从 [CDNJS](http://cdnjs.com/libraries/babel-core/5.8.34) 引用。Include `<script type="text/babel">` 标记来使用 JSX 转换器.
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 浏览器中的JSX转换器相当大并且导致额外的本可避免的客户端计算。不要在生产环境中使用 - 见下一节。
|
||||
|
||||
|
||||
### 投入生产: 预编译 JSX
|
||||
|
||||
如果你有[npm](https://www.npmjs.com/),你可以运行 `npm install -g babel`. Babel 对React v0.12 和 v0.13 有内建的支持。 标签被自动转化为它们的等价物`React.createElement(...)`, `displayName` 被自动推断并添加到所有的React.createClass 调用。
|
||||
如果你有[npm](https://www.npmjs.com/),你可以运行 `npm install -g babel-cli`. Babel 对React v0.12+ 有内建支持。 标签被自动转化为它们的等价物`React.createElement(...)`, `displayName` 被自动推断并添加到所有的React.createClass 调用。
|
||||
|
||||
这个工具会把使用JSX语法的文件转化为简单的可直接在浏览器运行的JavaScript文件。它同样将为你监视目录并自动转化文件当他们变动时;例如:`babel --watch src/ --out-dir lib/`.
|
||||
|
||||
从 Babel 6 开始,默认不再包含转换。这意味这必须在运行 `babel` 命令时指定选项,或者 `.babelrc` 必须指定选项。附加的捆绑了一大批转化的包(presets)也同样需要被安装.协同React工作最常用的是 `es2015` 和 `react` presets.更多关于 Babel 变化的信息可以在 [Babel 6 博客发布的信息](http://babeljs.io/blog/2015/10/29/6.0.0/)上找到.
|
||||
|
||||
这里是一个要使用ES2015 语法和 React 你该怎样做的例子:
|
||||
|
||||
```
|
||||
npm install babel-preset-es2015 babel-preset-react
|
||||
babel --presets es2015,react --watch src/ --out-dir lib/
|
||||
```
|
||||
|
||||
默认模式下带有`.js`后缀的JSX文件被转化。运行 `babel --help` 获取更多关于如何使用 Babel 的信息。
|
||||
|
||||
输出的例子:
|
||||
@@ -68,7 +75,6 @@ var HelloMessage = React.createClass({
|
||||
ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
|
||||
```
|
||||
|
||||
|
||||
### 有帮助的开源项目
|
||||
|
||||
开源社区已经创建了一些集成JSX到数个编辑器和构建系统的工具。参见[JSX integrations](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations) 查看全部列表。
|
||||
开源社区已经创建了一些集成JSX到数个编辑器和构建系统的工具。全部列表请见[JSX integrations](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations) 。
|
||||
|
||||
@@ -6,7 +6,7 @@ prev: tooling-integration-ko-KR.html
|
||||
next: animation-ko-KR.html
|
||||
---
|
||||
|
||||
`React.addons`은 React 앱을 만드는 데 유용한 유틸리티를 두는 곳입니다. **실험적인 기능으로 취급해야 하지만** 결국 코어나 유틸리티 라이브러리에 포함될 예정입니다.
|
||||
React 애드온은 React 앱을 만드는 데 유용한 유틸리티의 모음입니다. **실험적인 기능으로 취급해야 하고** 코어보다 더 자주 변경될 수 있습니다.
|
||||
|
||||
- [`TransitionGroup` 과 `CSSTransitionGroup`](animation-ko-KR.html)은 예를 들면 컴포넌트 삭제 직전의 트랜지션 처럼, 구현하기 까다로운 애니메이션과 트랜지션을 다룹니다.
|
||||
- [`LinkedStateMixin`](two-way-binding-helpers-ko-KR.html)는 사용자 입력과 컴포넌트의 state사이의 조정(coordination)을 단순화 합니다.
|
||||
@@ -20,6 +20,4 @@ next: animation-ko-KR.html
|
||||
- [`TestUtils`](test-utils-ko-KR.html)는 테스트 케이스를 적기 위한 간단한 헬퍼입니다. (압축되지 않은 빌드에서만 사용가능)
|
||||
- [`Perf`](perf-ko-KR.html)는 성능을 측정하고, 최적화를 위한 힌트를 제공합니다.
|
||||
|
||||
애드온을 쓰려면, 보통 `react.js` 대신 `react-with-addons.js`(혹은 압축판)을 사용해야 합니다.
|
||||
|
||||
npm을 이용해 React 패키지를 설치해 사용한다면, 그냥 `require('react')` 대신 `require('react/addons')`을 사용해 모든 애드온을 쓸 수 있습니다.
|
||||
애드온을 쓰려면, npm에서 각각 설치하세요.(예를 들면, `npm install react-addons-pure-render-mixin`) npm을 사용하지 않는 애드온 사용법에 대한 지원은 없습니다.
|
||||
|
||||
@@ -14,10 +14,11 @@ The React add-ons are a collection of useful utility modules for building React
|
||||
- [`createFragment`](create-fragment.html), to create a set of externally-keyed children.
|
||||
- [`update`](update.html), a helper function that makes dealing with immutable data in JavaScript easier.
|
||||
- [`PureRenderMixin`](pure-render-mixin.html), a performance booster under certain situations.
|
||||
- [`shallowCompare`](shallow-compare.html), a helper function that performs a shallow comparison for props and state in a component to decide if a component should update.
|
||||
|
||||
The add-ons below are in the development (unminified) version of React only:
|
||||
|
||||
- [`TestUtils`](test-utils.html), simple helpers for writing test cases (unminified build only).
|
||||
- [`Perf`](perf.html), for measuring performance and giving you hint where to optimize.
|
||||
- [`TestUtils`](test-utils.html), simple helpers for writing test cases.
|
||||
- [`Perf`](perf.html), a performance profiling tool for finding optimization opportunities.
|
||||
|
||||
To get the add-ons, install them individually from npm (e.g., `npm install react-addons-pure-render-mixin`). We don't support using the addons if you're not using npm.
|
||||
|
||||
@@ -6,20 +6,19 @@ prev: tooling-integration-zh-CN.html
|
||||
next: animation-zh-CN.html
|
||||
---
|
||||
|
||||
`React.addons` 是我们放置一些用来构建React apps的有用的工具的地方。 **这些应该被认为是实验性的** 但是最终批量进入核心代码或者一个有用的工具库中:
|
||||
React插件是一系列的用来构建 React app的有用模块。 **这些应该被认为是实验性的** 并趋向于比core变动更频繁。
|
||||
|
||||
- [`TransitionGroup` 和 `CSSTransitionGroup`](animation.html), 用来处理通常不能简单实现的动画和转换,比如在组件移除之前。
|
||||
- [`LinkedStateMixin`](two-way-binding-helpers.html), 简化用户的表单输入数据与组件状态的协调。
|
||||
- [`cloneWithProps`](clone-with-props.html), 创建React组件的浅拷贝并改变它们的props。
|
||||
- [`TransitionGroup` 和 `CSSTransitionGroup`](animation.html), 用来处理通常不能简单实现的动画和转换,比如在组件移除之前。
|
||||
- [`LinkedStateMixin`](two-way-binding-helpers.html), 简化用户的表单输入数据与组件状态的协调。
|
||||
- [`cloneWithProps`](clone-with-props.html), 创建React组件的浅拷贝并改变它们的props。
|
||||
- [`createFragment`](create-fragment.html), 创建一组外键的子级。
|
||||
- [`update`](update.html), 一个使不可变数据在JavaScript里更易处理的辅助函数。
|
||||
- [`update`](update.html), 一个使不可变数据在JavaScript里更易处理的辅助函数。
|
||||
- [`PureRenderMixin`](pure-render-mixin.html), 一个特定情况下的性能优化器。
|
||||
- [`shallowCompare`](shallow-compare.html), 一个辅助函数,用来对 props 和 state在组件里 执行浅比较 以决定一个组件是否应该更新。
|
||||
|
||||
下面的插件只存在开发版(未压缩)React中:
|
||||
|
||||
- [`TestUtils`](test-utils.html), 用于写测试用例的简单的辅助工具(仅存在于未压缩版本)。
|
||||
- [`Perf`](perf.html), 用于测量性能并给你提示哪里可以优化。
|
||||
- [`TestUtils`](test-utils.html), 用于写测试用例的简单的辅助工具。
|
||||
- [`Perf`](perf.html), 一个用于查找优化机会的性能分析工具。
|
||||
|
||||
要获取插件,使用 `react-with-addons.js` (和它的压缩副本)而不是通常的 `react.js`。
|
||||
|
||||
当从npm使用react包时,简单的用`require('react/addons')` 代替 `require('react')` 来获取带有所有插件的React。
|
||||
要获取插件,单独从npm安装他们(例如 `npm install react-addons-pure-render-mixin`).我们不支持使用插件如果你没有用npm.
|
||||
|
||||
@@ -44,7 +44,7 @@ var TodoList = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<button onClick={this.handleAdd}>Aggiungi Elemento</button>
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300} >
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300}>
|
||||
{items}
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
|
||||
@@ -199,7 +199,7 @@ var ImageCarousel = React.createClass({
|
||||
|
||||
### 異なるコンポーネントをレンダリングする
|
||||
|
||||
デフォルトで、 `ReactTransitionGroup` は `span` としてレンダリングされます。この動きは、 `component` プロパティによって変更できます。例えば、 `<ul>` をレンダリングしたい場合は以下のようになります。
|
||||
デフォルトで、 `ReactTransitionGroup` は `span` としてレンダリングされます。この動きは、 `component` プロパティによって変更できます。例えば、 `<ul>` をレンダリングしたい場合は以下のようになります。
|
||||
|
||||
```javascript{1}
|
||||
<ReactTransitionGroup component="ul">
|
||||
|
||||
@@ -18,7 +18,7 @@ React에는 애니메이션을 위한 저 수준 API로 `ReactTransitionGroup`
|
||||
`ReactCSSTransitionGroup`은 `ReactTransitions`을 위한 인터페이스입니다. 이는 애니메이션을 제어할 모든 컴포넌트를 감싸는 하나의 엘리먼트 입니다. 아래는 목록의 아이템을 페이드 인/아웃하는 간단한 예제입니다.
|
||||
|
||||
```javascript{28-30}
|
||||
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
|
||||
var TodoList = React.createClass({
|
||||
getInitialState: function() {
|
||||
@@ -45,7 +45,7 @@ var TodoList = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<button onClick={this.handleAdd}>Add Item</button>
|
||||
<ReactCSSTransitionGroup transitionName="example">
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300}>
|
||||
{items}
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
@@ -53,9 +53,10 @@ var TodoList = React.createClass({
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> `ReactCSSTransitionGroup`의 모든 자식은 [`key` 어트리뷰트](/react/docs/multiple-components-ko-KR.html#dynamic-children)를 반드시 만들어야 합니다. 한 아이템을 렌더한다 해도 예외는 아닙니다. 키는 React가 어떤 자식이 들어오고, 나가고, 머무르는지 파악할 때 사용합니다.
|
||||
> `ReactCSSTransitionGroup`의 모든 자식은 [`key` 어트리뷰트](/react/docs/multiple-components-ko-KR.html#dynamic-children)를 반드시 만들어야 합니다. 한 아이템을 렌더할 때도 예외는 아닙니다. 키는 React가 어떤 자식이 들어오고, 나가고, 머무르는지 파악할 때 사용합니다.
|
||||
|
||||
이 컴포넌트에서 새로운 아이템이 `ReactCSSTransitionGroup`에 추가되면 `example-enter` 아이템은 CSS 클래스를 가지게 되고 다음 순간에 `example-enter-active` CSS 클래스가 추가됩니다. 이는 `transitionName` prop을 기반으로 한 관례입니다.
|
||||
|
||||
@@ -68,23 +69,21 @@ var TodoList = React.createClass({
|
||||
|
||||
.example-enter.example-enter-active {
|
||||
opacity: 1;
|
||||
transition: opacity .5s ease-in;
|
||||
transition: opacity 500ms ease-in;
|
||||
}
|
||||
```
|
||||
|
||||
`ReactCSSTransitionGroup`에서 아이템을 제거하려해도 DOM에는 남게 됩니다. 만약 애드온을 React의 최소화하지 않은 빌드와 사용한다면, 애니메이션이나 트랜지션이 일어나는 것을 예상하고 있었다는 React의 경고를 보게 될 것입니다. 그게 바로 `ReactCSSTransitionGroup`가 DOM 엘리먼트를 애니메이션이 끝날 때까지 페이지에 남겨두는 이유입니다. 이 CSS를 넣어보세요.
|
||||
|
||||
```css
|
||||
.example-leave {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.example-leave.example-leave-active {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
```
|
||||
|
||||
에니메이션 기간이 CSS와 렌더 메소드 양쪽에 지정될 필요가 있다는 것에 주의하셔야 합니다. 이는 엘리먼트에서 애니메이션 클래스를 제거할 때 (만약 남아있다면) DOM에서 엘리먼트를 제거할 때 React에 알려줍니다.
|
||||
|
||||
### 처음 마운트에서 애니메이션 하기
|
||||
|
||||
`ReactCSSTransitionGroup`은 컴포넌트를 처음 마운트할 때 추가 트렌지션 단계를 추가하기 위해, 선택적인 prop `transitionAppear`를 제공합니다. 일반적으로 처음 마운트할 때 트렌지션 단계를 넣지 않기 때문에 `transitionAppear`의 기본 값은 `false`입니다. 뒤의 예제는 `transitionAppear` prop에 `true` 값을 넘기고 있습니다.
|
||||
@@ -92,7 +91,7 @@ var TodoList = React.createClass({
|
||||
```javascript{3-5}
|
||||
render: function() {
|
||||
return (
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true}>
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}>
|
||||
<h1>Fading at Initial Mount</h1>
|
||||
</ReactCSSTransitionGroup>
|
||||
);
|
||||
@@ -104,11 +103,11 @@ var TodoList = React.createClass({
|
||||
```css
|
||||
.example-appear {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
|
||||
.example-appear.example-appear-active {
|
||||
opacity: 1;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -125,23 +124,23 @@ var TodoList = React.createClass({
|
||||
```javascript
|
||||
...
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName={
|
||||
transitionName={ {
|
||||
enter: 'enter',
|
||||
enterActive: 'enterActive',
|
||||
leave: 'leave',
|
||||
leaveActive: 'leaveActive',
|
||||
appear: 'appear',
|
||||
appearActive: 'appearActive'
|
||||
}>
|
||||
} }>
|
||||
{item}
|
||||
</ReactCSSTransitionGroup>
|
||||
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName={
|
||||
transitionName={ {
|
||||
enter: 'enter',
|
||||
leave: 'leave',
|
||||
appear: 'appear'
|
||||
}>
|
||||
} }>
|
||||
{item2}
|
||||
</ReactCSSTransitionGroup>
|
||||
...
|
||||
@@ -176,7 +175,7 @@ var TodoList = React.createClass({
|
||||
위의 예제에서 `ReactCSSTransitionGroup`에 아이템 목록을 렌더했지만, `ReactCSSTransitionGroup`의 자식은 하나이거나 없을 수도 있습니다. 이는 한 엘리먼트가 들어오고 나가는 것의 애니메이션을 가능하게 합니다. 비슷하게, 현재 엘리먼트가 나가는 동안 새 앨리먼트의 애니메이션을 하면, 새 엘리먼트가 현재 엘리먼트를 교체하는 애니메이션을 만들 수 있습니다. 예를 들어 이렇게 간단한 이미지 회전 베너(carousel)를 구현할 수 있습니다.
|
||||
|
||||
```javascript{10-12}
|
||||
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
|
||||
var ImageCarousel = React.createClass({
|
||||
propTypes: {
|
||||
@@ -185,7 +184,7 @@ var ImageCarousel = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ReactCSSTransitionGroup transitionName="carousel">
|
||||
<ReactCSSTransitionGroup transitionName="carousel" transitionEnterTimeout={300} transitionLeaveTimeout={300}>
|
||||
<img src={this.props.imageSrc} key={this.props.imageSrc} />
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
@@ -204,7 +203,7 @@ var ImageCarousel = React.createClass({
|
||||
|
||||
## 저수준 API: `ReactTransitionGroup`
|
||||
|
||||
`ReactTransitionGroup`은 애니메이션의 기초입니다. 이는 `React.addons.TransitionGroup`으로 접근할 수 있습니다. 위에 있는 예제처럼 자식들이 선언적으로 여기에 추가되거나 삭제되는 경우, 특별한 훅이 이 생명주기에서 호출됩니다.
|
||||
`ReactTransitionGroup`은 애니메이션의 기초입니다. 이는 `require('react-addons-transition-group')`으로 접근할 수 있습니다. 위의 예제처럼 자식들이 선언적으로 여기에 추가되거나 삭제되는 경우, 특별한 훅이 이 생명주기에서 호출됩니다.
|
||||
|
||||
### `componentWillAppear(callback)`
|
||||
|
||||
@@ -240,11 +239,7 @@ var ImageCarousel = React.createClass({
|
||||
</ReactTransitionGroup>
|
||||
```
|
||||
|
||||
모든 React가 렌더할 수 있는 DOM 컴포넌트는 사용할 수 있습니다. 하지만 `component`가 DOM 컴포넌트일 필요는 없습니다. React 컴포넌트라면 무엇이든 넣을 수 있습니다. 직접 구현한 컴포넌트여도 됩니다!
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> v0.12이전에는, DOM 컴포넌트를 사용할 때, `component` prop은 `React.DOM.*`로 참조할 필요가 있었습니다. 이제 컴포넌트가 단순히 `React.createElement`로 전달되기 때문에, `component` prop은 스트링이어야 합니다. 복합 컴포넌트는 팩토리를 넘겨야 합니다.
|
||||
React가 렌더할 수 있는 DOM 컴포넌트는 전부 사용할 수 있습니다. 하지만 `component`가 DOM 컴포넌트일 필요는 없습니다. React 컴포넌트라면 무엇이든 넣을 수 있습니다. 직접 구현한 컴포넌트여도 됩니다! 그냥 `component={List}`를 적으면 컴포넌트는 `this.props.children`로 받을 수 있습니다.
|
||||
|
||||
사용자 정의를 포함한 어떤 프로퍼티도 렌더된 컴포넌트의 프로퍼티가 됩니다. 예를 들어, `<ul>`에 CSS 클래스를 넣어서 렌더하려면 이렇게 하면 됩니다.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ prev: addons.html
|
||||
next: two-way-binding-helpers.html
|
||||
---
|
||||
|
||||
React provides a `ReactTransitionGroup` addon component as a low-level API for animation, and a `ReactCSSTransitionGroup` for easily implementing basic CSS animations and transitions.
|
||||
React provides a `ReactTransitionGroup` add-on component as a low-level API for animation, and a `ReactCSSTransitionGroup` for easily implementing basic CSS animations and transitions.
|
||||
|
||||
## High-level API: `ReactCSSTransitionGroup`
|
||||
|
||||
@@ -29,7 +29,7 @@ var TodoList = React.createClass({
|
||||
this.setState({items: newItems});
|
||||
},
|
||||
handleRemove: function(i) {
|
||||
var newItems = this.state.items;
|
||||
var newItems = this.state.items.slice();
|
||||
newItems.splice(i, 1);
|
||||
this.setState({items: newItems});
|
||||
},
|
||||
@@ -44,7 +44,7 @@ var TodoList = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<button onClick={this.handleAdd}>Add Item</button>
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300} >
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300}>
|
||||
{items}
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
@@ -52,6 +52,7 @@ var TodoList = React.createClass({
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
> Note:
|
||||
>
|
||||
> You must provide [the `key` attribute](/react/docs/multiple-components.html#dynamic-children) for all children of `ReactCSSTransitionGroup`, even when only rendering a single item. This is how React will determine which children have entered, left, or stayed.
|
||||
|
||||
@@ -17,7 +17,7 @@ React 提供了一个 `ReactTransitionGroup` 插件作为动画的底层API,和
|
||||
`ReactCSSTransitionGroup` 是 `ReactTransitions` 的接口。这是一个简单的元素,包裹了所有你感兴趣的动画组件。这里是一个淡入和淡出列表项目的例子。
|
||||
|
||||
```javascript{28-30}
|
||||
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
|
||||
var TodoList = React.createClass({
|
||||
getInitialState: function() {
|
||||
@@ -29,7 +29,7 @@ var TodoList = React.createClass({
|
||||
this.setState({items: newItems});
|
||||
},
|
||||
handleRemove: function(i) {
|
||||
var newItems = this.state.items;
|
||||
var newItems = this.state.items.slice();
|
||||
newItems.splice(i, 1);
|
||||
this.setState({items: newItems});
|
||||
},
|
||||
@@ -44,7 +44,7 @@ var TodoList = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<button onClick={this.handleAdd}>Add Item</button>
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300} >
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300}>
|
||||
{items}
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
@@ -101,11 +101,11 @@ var TodoList = React.createClass({
|
||||
```css
|
||||
.example-appear {
|
||||
opacity: 0.01;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
|
||||
.example-appear.example-appear-active {
|
||||
opacity: 1;
|
||||
transition: opacity .5s ease-in;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -144,7 +144,7 @@ var TodoList = React.createClass({
|
||||
...
|
||||
```
|
||||
|
||||
### 动画组必须挂载才工作
|
||||
### 动画组必须挂载才工作
|
||||
|
||||
为了使过渡效果应用到子级上,`ReactCSSTransitionGroup`必须已经挂载到了DOM或者 prop `transitionAppear` 必须被设置为 `true`。下面的例子不会工作,因为 `ReactCSSTransitionGroup` 随同新项目被挂载,而不是新项目在它内部被挂载。将这与上面的[入门指南](#入门指南)部分比较一下,看看不同。
|
||||
|
||||
@@ -173,7 +173,7 @@ var TodoList = React.createClass({
|
||||
在上面的例子中,我们渲染了一系列的项目到`ReactCSSTransitionGroup`里。然而 `ReactCSSTransitionGroup` 的子级同样可以是一个或零个项目。这使它能够动画化单个元素的进入和离开。同样,你可以动画化一个新的元素替换当前元素。例如,我们可以像这样实现一个简单的图片轮播器:
|
||||
|
||||
```javascript{10-12}
|
||||
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
||||
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
|
||||
var ImageCarousel = React.createClass({
|
||||
propTypes: {
|
||||
@@ -201,7 +201,7 @@ var ImageCarousel = React.createClass({
|
||||
|
||||
## 底层 API: `ReactTransitionGroup`
|
||||
|
||||
`ReactTransitionGroup`是动画的基础。它通过 `React.addons.TransitionGroup` 访问。当子级被声明式的从其中添加或移除(就像上面的例子)时,特殊的生命周期挂钩会在它们上面被调用。
|
||||
`ReactTransitionGroup`是动画的基础。它通过 `require('react-addons-transition-group')` 访问。当子级被声明式的从其中添加或移除(就像上面的例子)时,特殊的生命周期挂钩会在它们上面被调用。
|
||||
|
||||
### `componentWillAppear(callback)`
|
||||
|
||||
@@ -237,11 +237,8 @@ var ImageCarousel = React.createClass({
|
||||
</ReactTransitionGroup>
|
||||
```
|
||||
|
||||
每一个React能渲染的DOM组件都是可用的。然而,`组件`不需要是一个DOM组件。它可以是任何你想要的React组件;甚至是你自己已经写好的!
|
||||
每一个React能渲染的DOM组件都是可用的。然而,`组件`不需要是一个DOM组件。它可以是任何你想要的React组件;甚至是你自己已经写好的!只要写 `component={List}` 你的组件会收到 `this.props.children`
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> v0.12之前,当使用DOM组件时,`组件` prop 需要是一个对`React.DOM.*`的引用。既然组件简单的被传递到 `React.createElement`,它现在必然是一个字符串。复合组件必须传递工厂函数(factory)。
|
||||
|
||||
任何额外的、用户定义的属性将会成为已渲染的组件的属性。例如,以下是你将如何渲染一个带有css类的 `<ul>`:
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user