Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dfd3948a9 | ||
|
|
b3ebab438b | ||
|
|
0070ad353a | ||
|
|
39ce13e9b3 | ||
|
|
6ed8e9d788 | ||
|
|
9eb86c14b4 | ||
|
|
c7a4196413 | ||
|
|
4decc08e53 | ||
|
|
76a30ace67 | ||
|
|
bdf263625d | ||
|
|
8c7bbbfc21 | ||
|
|
15631e02a2 | ||
|
|
1907f72934 | ||
|
|
ba62748217 | ||
|
|
224ace32be | ||
|
|
3ef748abb3 | ||
|
|
3f8b8d754c | ||
|
|
7a18e4e00b | ||
|
|
60ed71459c | ||
|
|
7b39bbaa91 | ||
|
|
2927c4ce76 | ||
|
|
3e47b3002b | ||
|
|
1bac6d567f | ||
|
|
92cfbf16c2 | ||
|
|
b445b26164 | ||
|
|
832c503c92 | ||
|
|
076d7fd63a | ||
|
|
3ed71070a3 | ||
|
|
08dbefedc7 | ||
|
|
4be377650e | ||
|
|
8898803b4a | ||
|
|
21f71d72f0 | ||
|
|
d79061e0c6 | ||
|
|
d951c560e4 | ||
|
|
6cf782b75c | ||
|
|
dca0f7315c | ||
|
|
0983d2dbcf | ||
|
|
d90cbec236 | ||
|
|
6e20d410bb | ||
|
|
b4f6460bff | ||
|
|
199056cf1b | ||
|
|
681c68c62a | ||
|
|
cc41ec258f | ||
|
|
3c0906ca24 | ||
|
|
60a3655469 | ||
|
|
15df676d2e | ||
|
|
e5276bbbe7 | ||
|
|
12ab5baff4 | ||
|
|
f120c1b78e | ||
|
|
421bb8c53a | ||
|
|
9fea8ec6c8 | ||
|
|
536f826b56 | ||
|
|
307b4ebcc9 | ||
|
|
e1a9eb13b1 | ||
|
|
51fe7e466e | ||
|
|
8403a28adc | ||
|
|
c4f8466d5d | ||
|
|
cc5889c543 | ||
|
|
9e88467485 | ||
|
|
bfb3852942 | ||
|
|
df4356133d | ||
|
|
814be45aa8 | ||
|
|
bab9227e9d | ||
|
|
2f1ce9169d | ||
|
|
b19f202542 | ||
|
|
71f12283d9 | ||
|
|
4c5882258c | ||
|
|
ce24114a01 | ||
|
|
8e79c9fd30 | ||
|
|
5372e66c0c | ||
|
|
94dbf619d3 | ||
|
|
9d7ceac1f3 | ||
|
|
6a992382a4 | ||
|
|
c93d0c4f30 | ||
|
|
f2010e5532 | ||
|
|
5dce7c21e3 | ||
|
|
382f1519b2 | ||
|
|
38914dfe6a | ||
|
|
f65d629541 | ||
|
|
7608eda1ff | ||
|
|
21d9b85d66 | ||
|
|
44fa2c83d1 | ||
|
|
bad1080586 | ||
|
|
992e11b852 | ||
|
|
043c249458 | ||
|
|
d551e19b18 | ||
|
|
58720d608e | ||
|
|
3c7f275f4f | ||
|
|
77d6143485 | ||
|
|
d0fc12db61 | ||
|
|
ae17ce5b03 | ||
|
|
8794c51389 | ||
|
|
8a1c16bf09 | ||
|
|
1f65b2901b | ||
|
|
9be069fb98 | ||
|
|
b194f66fbc | ||
|
|
1d4e8c958d | ||
|
|
b071f10dd7 | ||
|
|
44f63165cb | ||
|
|
cc01d1be33 |
3
.babelrc
3
.babelrc
@@ -2,8 +2,9 @@
|
||||
"presets": ["react"],
|
||||
"ignore": ["third_party"],
|
||||
"plugins": [
|
||||
"transform-class-properties",
|
||||
"syntax-trailing-function-commas",
|
||||
"babel-plugin-transform-object-rest-spread",
|
||||
"transform-object-rest-spread",
|
||||
"transform-es2015-template-literals",
|
||||
"transform-es2015-literals",
|
||||
"transform-es2015-arrow-functions",
|
||||
|
||||
52
CHANGELOG.md
52
CHANGELOG.md
@@ -1,3 +1,53 @@
|
||||
## 15.3.2 (September 19, 2016)
|
||||
|
||||
### React
|
||||
- Remove plain object warning from React.createElement & React.cloneElement. ([@spudly](https://github.com/spudly] in [#7724](https://github.com/facebook/react/pull/7724])
|
||||
|
||||
### React DOM
|
||||
- Add `playsInline` to supported HTML attributes. ([@reaperhulk](https://github.com/reaperhulk] in [#7519](https://github.com/facebook/react/pull/7519])
|
||||
- Add `as` to supported HTML attributes. ([@kevinslin](https://github.com/kevinslin] in [#7582](https://github.com/facebook/react/pull/7582])
|
||||
- Improve DOM nesting validation warning about whitespace. ([@spicyj](https://github.com/spicyj] in [#7515](https://github.com/facebook/react/pull/7515])
|
||||
- Avoid "Member not found" exception in IE10 when calling `preventDefault()` in Synthetic Events. ([@g-palmer](https://github.com/g-palmer] in [#7411](https://github.com/facebook/react/pull/7411])
|
||||
- Fix memory leak in `onSelect` implementation. ([@AgtLucas](https://github.com/AgtLucas] in [#7533](https://github.com/facebook/react/pull/7533])
|
||||
- Improve robustness of `document.documentMode` checks to handle Google Tag Manager. ([@SchleyB](https://github.com/SchleyB] in [#7594](https://github.com/facebook/react/pull/7594])
|
||||
- Add more cases to controlled inputs warning. ([@marcin-mazurek](https://github.com/marcin-mazurek] in [#7544](https://github.com/facebook/react/pull/7544])
|
||||
- Handle case of popup blockers overriding `document.createEvent`. ([@Andarist](https://github.com/Andarist] in [#7621](https://github.com/facebook/react/pull/7621])
|
||||
- Fix issue with `dangerouslySetInnerHTML` and SVG in Internet Explorer. ([@zpao](https://github.com/zpao] in [#7618](https://github.com/facebook/react/pull/7618])
|
||||
- Improve handling of Japanese IME on Internet Explorer. ([@msmania](https://github.com/msmania] in [#7107](https://github.com/facebook/react/pull/7107])
|
||||
|
||||
### React Test Renderer
|
||||
- Support error boundaries. ([@millermedeiros](https://github.com/millermedeiros] in [#7558](https://github.com/facebook/react/pull/7558], [#7569](https://github.com/facebook/react/pull/7569], [#7619](https://github.com/facebook/react/pull/7619])
|
||||
- Skip null ref warning. ([@Aweary](https://github.com/Aweary] in [#7658](https://github.com/facebook/react/pull/7658])
|
||||
|
||||
### React Perf Add-on
|
||||
- Ensure lifecycle timers are stopped on errors. ([@gaearon](https://github.com/gaearon] in [#7548](https://github.com/facebook/react/pull/7548])
|
||||
|
||||
|
||||
## 15.3.1 (August 19, 2016)
|
||||
|
||||
### React
|
||||
|
||||
- Improve performance of development builds in various ways. ([@gaearon](https://github.com/gaearon) in [#7461](https://github.com/facebook/react/pull/7461), [#7463](https://github.com/facebook/react/pull/7463), [#7483](https://github.com/facebook/react/pull/7483), [#7488](https://github.com/facebook/react/pull/7488), [#7491](https://github.com/facebook/react/pull/7491), [#7510](https://github.com/facebook/react/pull/7510))
|
||||
- Cleanup internal hooks to improve performance of development builds. ([@gaearon](https://github.com/gaearon) in [#7464](https://github.com/facebook/react/pull/7464), [#7472](https://github.com/facebook/react/pull/7472), [#7481](https://github.com/facebook/react/pull/7481), [#7496](https://github.com/facebook/react/pull/7496))
|
||||
- Upgrade fbjs to pick up another performance improvement from [@gaearon](https://github.com/gaearon) for development builds. ([@zpao](https://github.com/zpao) in [#7532](https://github.com/facebook/react/pull/7532))
|
||||
- Improve startup time of React in Node. ([@zertosh](https://github.com/zertosh) in [#7493](https://github.com/facebook/react/pull/7493))
|
||||
- Improve error message of `React.Children.only`. ([@spicyj](https://github.com/spicyj) in [#7514](https://github.com/facebook/react/pull/7514))
|
||||
|
||||
### React DOM
|
||||
- Avoid `<input>` validation warning from browsers when changing `type`. ([@nhunzaker](https://github.com/nhunzaker) in [#7333](https://github.com/facebook/react/pull/7333))
|
||||
- Avoid "Member not found" exception in IE10 when calling `stopPropagation()` in Synthetic Events. ([@nhunzaker](https://github.com/nhunzaker) in [#7343](https://github.com/facebook/react/pull/7343))
|
||||
- Fix issue resulting in inability to update some `<input>` elements in mobile browsers. ([@keyanzhang](https://github.com/keyanzhang) in [#7397](https://github.com/facebook/react/pull/7397))
|
||||
- Fix memory leak in server rendering. ([@keyanzhang](https://github.com/keyanzhang) in [#7410](https://github.com/facebook/react/pull/7410))
|
||||
- Fix issue resulting in `<input type="range">` values not updating when changing `min` or `max`. ([@troydemonbreun](https://github.com/troydemonbreun) in [#7486](https://github.com/facebook/react/pull/7486))
|
||||
- Add new warning for rare case of attempting to unmount a container owned by a different copy of React. ([@ventuno](https://github.com/ventuno) in [#7456](https://github.com/facebook/react/pull/7456))
|
||||
|
||||
### React Test Renderer
|
||||
- Fix ReactTestInstance::toJSON() with empty top-level components. ([@Morhaus](https://github.com/Morhaus) in [#7523](https://github.com/facebook/react/pull/7523))
|
||||
|
||||
### React Native Renderer
|
||||
- Change `trackedTouchCount` invariant into a console.error for better reliability. ([@yungsters](https://github.com/yungsters) in [#7400](https://github.com/facebook/react/pull/7400))
|
||||
|
||||
|
||||
## 15.3.0 (July 29, 2016)
|
||||
|
||||
### React
|
||||
@@ -443,7 +493,7 @@ Each of these changes will continue to work as before with a new warning until t
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* Immutabilty Helpers: Ensure it supports `hasOwnProperty` as an object key
|
||||
* Immutability Helpers: Ensure it supports `hasOwnProperty` as an object key
|
||||
|
||||
### React Tools
|
||||
|
||||
|
||||
@@ -31,16 +31,16 @@ You'll notice that we used an HTML-like syntax; [we call it JSX](https://faceboo
|
||||
|
||||
## Installation
|
||||
|
||||
The fastest way to get started is to serve JavaScript from the CDN (also available on [cdnjs](https://cdnjs.com/libraries/react) and [jsdelivr](https://www.jsdelivr.com/projects/react)):
|
||||
The fastest way to get started is to serve JavaScript from a CDN. We're using [unpkg](https://unpkg.com/) below but React is also available on [cdnjs](https://cdnjs.com/libraries/react) and [jsdelivr](https://www.jsdelivr.com/projects/react):
|
||||
|
||||
```html
|
||||
<!-- The core React library -->
|
||||
<script src="https://fb.me/react-15.3.0.js"></script>
|
||||
<script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
|
||||
<!-- The ReactDOM Library -->
|
||||
<script src="https://fb.me/react-dom-15.3.0.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
|
||||
```
|
||||
|
||||
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-15.3.0.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
|
||||
We've also built a [starter kit](https://facebook.github.io/react/downloads/react-15.3.2.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
|
||||
|
||||
If you'd like to use [bower](http://bower.io), it's as easy as:
|
||||
|
||||
|
||||
5
build.sh
Normal file
5
build.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
grunt build:npm-react
|
||||
cd build/packages/react
|
||||
deps link
|
||||
npm install
|
||||
cd ../../..
|
||||
@@ -53,13 +53,13 @@ sass:
|
||||
gems:
|
||||
- jekyll-redirect-from
|
||||
- jekyll-paginate
|
||||
react_version: 15.2.1
|
||||
react_version: 15.3.1
|
||||
react_hashes:
|
||||
dev: g2900ZIpFKhyIsz+bnx4YDEfAISugYRU58ljeAgI8TZ0A0AkRLGUCN7OmjF16Cj+
|
||||
prod: ICzDcvbNpMy31akJ8WzksHoK9tl1iRIUPRCaBRN+sn/k40TNGjs9IvgPN0SekkDT
|
||||
addons_dev: js+Yc2Nd259A4+UPokRNVOXJdipY9oIrkkDdFJAZzZxgryRJLkWYDrJVgM97aweF
|
||||
addons_prod: DaNE8gIDQr8RWDoa4y9HX/70fzdOBzpV/e+7RJtMN1MnXEiCMpiIFtutJml6mvPC
|
||||
dom_dev: LD1cH7LXOdrrq5dOOiE2N/HdgCyrw3nmUMq6oPFCJKUfWO3i7AozvBKz7G3maMHt
|
||||
dom_prod: 1dLXeik7kFcDPXbz3rX9dibLTGh/D8dpAOL5X2Ml09pH8wpQlpL+JOgOnzAMCO4T
|
||||
dom_server_dev: WJt1y2JljJEQ1OgpupP2ly0GgIwi7Aodp+n+/fv2bakpgWpXMnLklj5rSouRJt59
|
||||
dom_server_prod: Y6UDASOvQhWWBwXy/Ccp4vSAt0YAp+ymuRXBX4hffy+pMlOgjXzryIjbiceIB6GF
|
||||
dev: gS+zau+tpUQYisQ0pOWmfNOfcczNoZQjeQ6+5jOgVqV1WBYqkIbdqpay3VuCHQjt
|
||||
prod: GjSRThJn3fjCmKim4Jou04Ax7vvKfk76xSCKUo7/V70VNIlidvZd3ZnT9rtJk0KM
|
||||
addons_dev: 37FL10I5CNyIhpG9UrOeUrUKONP5CUt3PYHxWz9Eo4kYWS7weaFzDRP7BxRfhB75
|
||||
addons_prod: hSlojvw2moZ49rKg6U9wW83sJi7QnWC6nB53jlsGy5hmltJC6ET/cRRKzMifYEg5
|
||||
dom_dev: yMyOXveaWIIfHWhBZNUrKSPQCw+BWRGucJIdsQeltkvBNDrWXKo+jKVKyx6hH/5r
|
||||
dom_prod: 3AR/0xGUlR37VpbeHbKQhvizC4T8sNTU8t5GS9JC/4odeRePZuPYl5Pyv/zTeSd8
|
||||
dom_server_dev: sPg6+OzdWmnH1aArppe66vtLc7tZ2gxh5KxXoZFHAxZoquTi4J71PHASGmv7meE1
|
||||
dom_server_prod: L4CScwloTXP7xdPmmp3KRAKqASCN8hQpjM6DsrAyCl4K8RXi8Ig+9i0X6k8AyfM9
|
||||
|
||||
@@ -2,14 +2,17 @@ require 'redcarpet'
|
||||
require 'sanitize'
|
||||
|
||||
# Simple converter that is probably better than RedCarpet's built in TOC id
|
||||
# generator (which ends up with things lik id="toc_1"... terrible).
|
||||
# generator (which ends up with things like id="toc_1"... terrible).
|
||||
|
||||
class Redcarpet::Render::HTML
|
||||
def header(title, level)
|
||||
# \p{Common} does not seem to include some of the Japanese alphabets and also includes
|
||||
# some undesired characters like colon and parentheses, so we have to write out the
|
||||
# necessary Unicode scripts individually.
|
||||
clean_title = Sanitize.clean(title)
|
||||
.downcase
|
||||
.gsub(/\s+/, "-")
|
||||
.gsub(/[^A-Za-z0-9\-_.]/, "")
|
||||
.gsub(/[^A-Za-z0-9\-_.\p{Cyrillic}\p{Hangul}\p{Hiragana}\p{Katakana}\p{Han}]/, "")
|
||||
|
||||
return "<h#{level}><a class=\"anchor\" name=\"#{clean_title}\"></a>#{title} <a class=\"hash-link\" href=\"##{clean_title}\">#</a></h#{level}>"
|
||||
end
|
||||
|
||||
81
docs/_posts/2016-08-05-relay-state-of-the-state.md
Normal file
81
docs/_posts/2016-08-05-relay-state-of-the-state.md
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: "Relay: State of the State"
|
||||
author: josephsavona
|
||||
---
|
||||
|
||||
This month marks a year since we released Relay and we'd like to share an update on the project and what's next.
|
||||
|
||||
## A Year In Review
|
||||
|
||||
A year after launch, we're incredibly excited to see an active community forming around Relay and that companies such as Twitter are [using Relay in production](https://fabric.io/blog/building-fabric-mission-control-with-graphql-and-relay):
|
||||
|
||||
> For a project like mission control, GraphQL and Relay were a near-perfect solution, and the cost of building it any other way justified the investment.
|
||||
>
|
||||
> -- <cite>Fin Hopkins</cite>
|
||||
|
||||
This kind of positive feedback is really encouraging (I'll admit to re-reading that post far too many times), and great motivation for us to keep going and make Relay even better.
|
||||
|
||||
With the community's help we've already come a long way since the technical preview. Here are some highlights:
|
||||
|
||||
- In March we added support for server-side rendering and for creating multiple instances of Relay on a single page. This was a coordinated effort over the course of several months by community members [Denis Nedelyaev](https://github.com/denvned) and [Gerald Monaco](https://github.com/devknoll) (now at Facebook).
|
||||
- Also in March we added support for React Native. While we use Relay and React Native together internally, they didn't quite work together in open-source out of the box. We owe a big thanks to [Adam Miskiewicz](https://github.com/skevy), [Tom Burns](https://github.com/boourns), [Gaëtan Renaudeau](https://github.com/gre), [David Aurelio](https://github.com/davidaurelio), [Martín Bigio](https://github.com/martinbigio), [Paul O’Shannessy](https://github.com/zpao), [Ben Alpert](https://github.com/spicyj), and many others who helped track down and resolve issues. Finally, thanks to [Steven Luscher](https://github.com/steveluscher) for coordinating this effort and building the first Relay/ReactNative example app.
|
||||
|
||||
We've also seen some great open-source projects spring up around Relay:
|
||||
|
||||
- [Denis Nedelyaev](https://github.com/denvned) created [isomorphic-relay](https://github.com/denvned/isomorphic-relay/), a package that helps developers build server-rendered Relay apps where data is prepared on the server and then used to bootstrap the app on the client.
|
||||
- [Jimmy Jia](https://github.com/taion) created [react-router-relay](https://github.com/relay-tools/react-router-relay) to integrate Relay data-fetching into React Router.
|
||||
- [Pavel Chertorogov](https://github.com/nodkz) released [relay-network-layer](https://github.com/nodkz/react-relay-network-layer), which adds features such as batching query requests, middleware, authentication, logging, and more.
|
||||
|
||||
This is just a small sampling of the community's contributions. So far we've merged over 300 PRs - about 25% of our commits - from over 80 of you. These PRs have improved everything from the website and docs down the very core of the framework. We're humbled by these outstanding contributions and excited to keep working with each of you!
|
||||
|
||||
# Retrospective & Roadmap
|
||||
|
||||
Earlier this year we paused to reflect on the state of the project. What was working well? What could be improved? What features should we add, and what could we remove? A few themes emerged: performance on mobile, developer experience, and empowering the community.
|
||||
|
||||
## Mobile Perf
|
||||
|
||||
First, Relay was built to serve the needs of product developers at Facebook. In 2016, that means helping developers to build apps that work well on [mobile devices connecting on slower networks](https://newsroom.fb.com/news/2015/10/news-feed-fyi-building-for-all-connectivity/). For example, people in developing markets commonly use [2011 year-class phones](https://code.facebook.com/posts/307478339448736/year-class-a-classification-system-for-android/) and connect via [2G class networks](https://code.facebook.com/posts/952628711437136/classes-performance-and-network-segmentation-on-android/). These scenarios present their own challenges.
|
||||
|
||||
Therefore, one of our primary goals this year is to optimize Relay for performance on low-end mobile devices *first*, knowing that this can translate to improved performance on high-end devices as well. In addition to standard approaches such as benchmarking, profiling, and optimizations, we're also working on big-picture changes.
|
||||
|
||||
For example, in today's Relay, here's what happens when an app is opened. First, React Native starts initializing the JavaScript context (loading and parsing your code and then running it). When this finishes, the app executes and Relay sees that you need data. It constructs and prints the query, uploads the query text to the server, processes the response, and renders your app. (Note that this process applies on the web, except that the code has to be *downloaded* instead of loaded from the device.)
|
||||
|
||||
Ideally, though, we could begin fetching data as soon as the native code had loaded - in parallel with the JS context initialization. By the time your JS code was ready to run, the data-fetching would already be under way. To do this we would need a way to determine *statically* - at build time - what query an application would send.
|
||||
|
||||
The key is that GraphQL is already static - we just need to fully embrace this fact. More on this later.
|
||||
|
||||
## Developer Experience
|
||||
|
||||
Next, we've paid attention to the community's feedback and know that, to put it simply, Relay could be "easier" to use (and "simpler" too). This isn't entirely surprising to us - Relay was originally designed as a routing library and gradually morphed into a data-fetching library. Concepts like Relay "routes", for example, no longer serve as critical a role and are just one more concept that developers have to learn about. Another example is mutations: while writes *are* inherently more complex than reads, our API doesn't make the simple things simple enough.
|
||||
|
||||
Alongside our focus on mobile performance, we've also kept the developer experience in mind as we evolve Relay core.
|
||||
|
||||
## Empowering the Community
|
||||
|
||||
Finally, we want to make it easier for people in the community to develop useful libraries that work with Relay. By comparison, React's small surface area - components - allows developers to build cool things like routing, higher-order components, or reusable text editors. For Relay, this would mean having the framework provide core primitives that users can build upon. We want it to be possible for the community to integrate Relay with view libraries other than React, or to build real-time subscriptions as a complementary library.
|
||||
|
||||
# What's Next
|
||||
|
||||
These were big goals, and also a bit scary; we knew that incremental improvements would only allow us to move so fast. So in April we started a project to build a new implementation of Relay core targeting low-end mobile devices from the start.
|
||||
|
||||
As you can guess since we're writing this, the experiment was a success. The result is a new core that retains the best parts of Relay today - colocated components & data-dependencies, automatic data/view consistency, declarative data-fetching - while improving performance on mobile devices and addressing several common areas of confusion.
|
||||
|
||||
We're currently focused on shipping the first applications using the new core: ironing out bugs, refining the API changes and developer experience, and adding any missing features. We're excited to bring these changes to open source, and will do so once we've proven them in production. We'll go into more detail in some upcoming talks - links below - but for now here's an overview:
|
||||
|
||||
- **Static Queries**: By adding a couple of Relay-specific directives, we've been able to retain the expressivity of current Relay queries using static syntax (concretely: you know what query an app will execute just by looking at the source text, without having to run that code). For starters this will allow Relay apps to start fetching data in parallel with JavaScript initialization. But it also unlocks other possibilities: knowing the query ahead of time means that we can generate optimized code for handling query responses, for example, or for reading query data from an offline cache.
|
||||
- **Expressive Mutations**: We'll continue to support a higher-level mutation API for common cases, but will also provide a lower-level API that allows "raw" data access where necessary. If you need to order a list of cached elements, for example, there will be a way to `sort()` it.
|
||||
- **Route-less Relay**: Routes will be gone in open source. Instead of a route with multiple query definitions, you'll just provide a single query with as many root fields as you want.
|
||||
- **Cache Eviction/Garbage Collection**: The API and architecture is designed from the start to allow removing cached data that is no longer referenced by a mounted view.
|
||||
|
||||
Stepping back, we recognize that any API changes will require an investment on your part. To make the transition easier, though, *we will continue to support the current API for the foreseeable future* (we're still using it too). And as much as possible we will open-source the tools that we use to migrate our own code. Ideas that we're exploring include codemods, an interoperability layer for the old/new APIs, and tutorials & guides to ease migration.
|
||||
|
||||
Ultimately, we're making these changes because we believe they make Relay better all around: simpler for developers building apps and faster for the people using them.
|
||||
|
||||
# Conclusion
|
||||
|
||||
If you made it this far, congrats and thanks for reading! We'll be sharing more information about these changes in some upcoming talks:
|
||||
|
||||
- [Greg Hurrell](https://github.com/wincent) will presenting a Relay "Deep Dive" at the [Silicon Valley ReactJS Meetup](http://www.meetup.com/Silicon-Valley-ReactJS-Meetup/events/232236845/) on August 17th.
|
||||
- I ([@josephsavona](https://github.com/josephsavona)) will be speaking about Relay at [React Rally](http://www.reactrally.com) on August 25th.
|
||||
|
||||
We can't wait to share the new code with you and are working as fast as we can to do so!
|
||||
@@ -19,8 +19,9 @@ Diamo un'occhiata ad un esempio davvero semplice. Creiamo un file dal nome `hell
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -19,8 +19,9 @@ UIについて、最も基本的なことは、いくつかのデータを表示
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -18,9 +18,9 @@ UI를 가지고 할 수 있는 가장 기초적인 것은 데이터를 표시하
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -18,9 +18,9 @@ Let's look at a really simple example. Create a `hello-react.html` file with the
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -18,9 +18,9 @@ next: jsx-in-depth.html
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -18,9 +18,9 @@ next: jsx-in-depth-zh-CN.html
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: displaying-data-zh-TW
|
||||
title: Displaying Data
|
||||
permalink: displaying-data-zh-TW.html
|
||||
permalink: docs/displaying-data-zh-TW.html
|
||||
prev: why-react-zh-TW.html
|
||||
next: jsx-in-depth-zh-TW.html
|
||||
---
|
||||
@@ -18,9 +18,9 @@ next: jsx-in-depth-zh-TW.html
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -45,7 +45,6 @@ React JSX는 대소문자를 로컬 컴포넌트 클래스와 HTML 태그를 구
|
||||
> 권장하지 않습니다. 대신, React DOM 컴포넌트는 각각 `className`, `htmlFor`같은
|
||||
> DOM 프로퍼티 이름을 기대합니다.
|
||||
|
||||
<a name="the-transform"></a>
|
||||
## 변환
|
||||
|
||||
React JSX는 XML같은 문법에서 네이티브 JavaScript로 변환됩니다. XML 엘리먼트, 어트리뷰트, 자식은 `React.createElement`에 넘겨지는 인자로 변환됩니다.
|
||||
@@ -74,7 +73,7 @@ var app = React.createElement(
|
||||
);
|
||||
```
|
||||
|
||||
클래스에 [displayName](/react/docs/component-specs-ko-KR.html#displayName)이 정의되어 있지 않으면 JSX는 변수명을 displayName으로 간주할 것입니다:
|
||||
클래스에 [displayName](/react/docs/component-specs-ko-KR.html#displayname)이 정의되어 있지 않으면 JSX는 변수명을 displayName으로 간주할 것입니다:
|
||||
|
||||
```javascript
|
||||
// 입력 (JSX):
|
||||
|
||||
@@ -105,7 +105,6 @@ React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트
|
||||
</Card>
|
||||
```
|
||||
|
||||
<a name="dynamic-children"></a>
|
||||
### 동적 자식
|
||||
|
||||
자식들이 섞이거나(검색의 결과같은 경우) 새로운 컴포넌트가 목록의 앞에 추가(스트림같은 경우)된다면 상황은 점점 더 까다로워집니다. 이런 때에의 동일성과 각 자식의 상태는 반드시 렌더 패스 간에 유지돼야 합니다. 각 자식에 `key`를 할당 함으로써 독자적으로 식별할 수 있습니다.
|
||||
|
||||
@@ -140,7 +140,7 @@ var MyComponent = React.createClass({
|
||||
|
||||
컴포넌트는 React에서 코드를 재사용할 수 있는 최고의 방법이지만, 가끔 아주 다른 컴포넌트에서 공통 기능이 필요한 때도 있습니다. 이런 상황을 [공통된 관심사(cross-cutting concerns)](https://en.wikipedia.org/wiki/Cross-cutting_concern)라 부르며, React에서는 `mixins`으로 이 문제를 해결합니다.
|
||||
|
||||
예를 들어, 컴포넌트가 주기적으로 업데이트되길 원할 경우가 있습니다. `setInterval()`을 사용하면 쉽지만, 필요 없어지면 메모리를 아끼기 위해 주기를 꼭 취소해야 합니다. React는 컴포넌트가 막 생성거나 없어질 때를 [생명주기 메소드](/react/docs/working-with-the-browser-ko-KR.html#component-lifecycle)를 통해 알려줍니다. 이런 메소드들을 사용해서 컴포넌트가 사라질 때 자동으로 정리해주는 `setInterval()`를 제공해주는 간단한 믹스인을 만들어보겠습니다.
|
||||
예를 들어, 컴포넌트가 주기적으로 업데이트되길 원할 경우가 있습니다. `setInterval()`을 사용하면 쉽지만, 필요 없어지면 메모리를 아끼기 위해 주기를 꼭 취소해야 합니다. React는 컴포넌트가 막 생성거나 없어질 때를 [생명주기 메소드](/react/docs/working-with-the-browser-ko-KR.html#컴포넌트-생명주기)를 통해 알려줍니다. 이런 메소드들을 사용해서 컴포넌트가 사라질 때 자동으로 정리해주는 `setInterval()`를 제공해주는 간단한 믹스인을 만들어보겠습니다.
|
||||
|
||||
```javascript
|
||||
var SetIntervalMixin = {
|
||||
@@ -183,7 +183,6 @@ ReactDOM.render(
|
||||
|
||||
믹스인의 괜찮은 점은 컴포넌트가 여러 믹스인을 사용하고 여러 믹스인에서 같은 생명주기 메소드를 사용할 때(예를 들어, 여러 믹스인에서 컴포넌트가 사라질 때 뭔가 정리하려 한다면) 모든 생명주기 메소드들의 실행은 보장됩니다. 믹스인에 정의된 메소드은 컴포넌트의 메소드가 호출됨에 따라 믹스인이 나열된 순서대로 실행됩니다.
|
||||
|
||||
<a name="es6-classes"></a>
|
||||
## ES6 클래스
|
||||
|
||||
React 클래스를 일반적인 JavaScript 클래스로 선언할 수도 있습니다. 다음의 예제는 ES6 클래스 문법을 사용합니다:
|
||||
@@ -230,7 +229,6 @@ Counter.defaultProps = { initialCount: 0 };
|
||||
|
||||
불행하게도 ES6는 믹스인에 대한 지원이 없이 출시되었기 때문에, React에서 ES6 클래스를 사용한다면 믹스인을 사용할 방법이 없습니다. 대신, 우리는 믹스인에 의존하지 않고도 동작하도록 만들기 위해 열심히 노력하고 있습니다.
|
||||
|
||||
<a name="stateless-functions"></a>
|
||||
## 상태를 가지지 않는 함수
|
||||
|
||||
React 클래스를 일반 JavaScript 함수로 작성할 수도 있습니다. 상태를 가지지 않는 함수 문법을 사용하는 예제입니다.
|
||||
|
||||
@@ -294,7 +294,19 @@ 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.
|
||||
|
||||
However, you may still specify `.propTypes` and `.defaultProps` by setting them as properties on the function, just as you would set them on an ES6 class:
|
||||
|
||||
```javascript
|
||||
const HelloMessage = (props) => <div>Hello, {props.name}</div>;
|
||||
HelloMessage.propTypes = {
|
||||
name: React.PropTypes.string
|
||||
}
|
||||
HelloMessage.defaultProps = {
|
||||
name: 'John Doe'
|
||||
}
|
||||
ReactDOM.render(<HelloMessage name="Mădălina"/>, mountNode);
|
||||
```
|
||||
|
||||
> NOTE:
|
||||
>
|
||||
|
||||
@@ -50,7 +50,7 @@ ReactDOM.render(
|
||||
## JSXにおける `...` を使った移譲
|
||||
|
||||
> 注意:
|
||||
> 以下の例では、実験的なES7のシンタックスであることを示すために `--harmony ` フラグが必要になります。ブラウザ上でJSXトランスフォーマーを使う際には、単純に `<script type="text/jsx;harmony=true">` を使ってスクリプトを読み込んでください。詳細については、 [レストとスプレッドのプロパティ ...](/react/docs/transferring-props.html#rest-and-spread-properties-...)をご覧ください。
|
||||
> 以下の例では、実験的なES7のシンタックスであることを示すために `--harmony ` フラグが必要になります。ブラウザ上でJSXトランスフォーマーを使う際には、単純に `<script type="text/jsx;harmony=true">` を使ってスクリプトを読み込んでください。詳細については、 [レストとスプレッドのプロパティ ...](/react/docs/transferring-props-ja-JP.html#レストとスプレッドのプロパティ-...)をご覧ください。
|
||||
|
||||
全てのプロパティを渡すのはバグを生みやすく、面倒くさいときがあります。そのようなケースでは、未知のプロパティのセットを使うためにレストプロパティと共に[分割代入引数](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)を使うことができます。
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ ReactDOM.render(
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 在下面的例子中,`--harmony ` 标志是必须的因为这个语法是ES7的实验性语法。如果用浏览器中的JSX转换器,以 `<script type="text/jsx;harmony=true">`简单的打开你脚本就行了。详见[Rest and Spread Properties ...](/react/docs/transferring-props.html#rest-and-spread-properties-...)
|
||||
> 在下面的例子中,`--harmony ` 标志是必须的因为这个语法是ES7的实验性语法。如果用浏览器中的JSX转换器,以 `<script type="text/jsx;harmony=true">`简单的打开你脚本就行了。详见[Rest and Spread Properties ...](/react/docs/transferring-props-zh-CN.html#剩余属性和展开属性-...)
|
||||
|
||||
有时把所有属性都传下去是不安全或啰嗦的。这时可以使用 [解构赋值](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) 中的剩余属性特性来把未知属性批量提取出来。
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ next: working-with-the-browser-ko-KR.html
|
||||
|
||||
`<input>`, `<textarea>`, `<option>` 같은 폼 컴포넌트는 다른 네이티브 컴포넌트와 다릅니다. 왜냐하면, 사용자의 상호작용에 의해 변경될 수 있기 때문이죠. 이런 컴포넌트들은 사용자의 상호작용에 반응하여 폼을 더 쉽게 관리할 수 있도록 인터페이스를 제공합니다.
|
||||
|
||||
`<form>` 이벤트에 관한 정보는 [폼 이벤트](/react/docs/events-ko-KR.html#form-events)를 보세요.
|
||||
`<form>` 이벤트에 관한 정보는 [폼 이벤트](/react/docs/events-ko-KR.html#폼-이벤트)를 보세요.
|
||||
|
||||
## Props의 상호작용
|
||||
|
||||
@@ -32,7 +32,6 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
>
|
||||
> `<input>`, `<textarea>`에서는 `onChange`가 DOM의 [`oninput`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput) 이벤트 핸들러와 같은 기능을 제공하므로 일반적인 경우에는 `onChange`를 사용하세요.
|
||||
|
||||
<a name="controlled-components"></a>
|
||||
## 제어되는(controlled) 컴포넌트
|
||||
|
||||
`value`가 설정된 `<input>`은 *제어되는* 컴포넌트입니다. 제어되는 `<input>`에서, 렌더 엘리먼트의 값은 항상 `value` prop을 반영합니다. 예를 들어,
|
||||
@@ -100,7 +99,7 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> `defaultValue`, `defaultChecked` prop은 최초 렌더에서만 사용됩니다. 뒤에 일어나는 렌더에서 값을 업데이트할 필요가 있다면, [제어되는(controlled) 컴포넌트](#controlled-components)를 사용하셔야 합니다.
|
||||
> `defaultValue`, `defaultChecked` prop은 최초 렌더에서만 사용됩니다. 뒤에 일어나는 렌더에서 값을 업데이트할 필요가 있다면, [제어되는(controlled) 컴포넌트](#제어되는controlled-컴포넌트)를 사용하셔야 합니다.
|
||||
|
||||
## 심화 주제
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ next: working-with-the-browser-zh-CN.html
|
||||
|
||||
诸如 `<input>`、`<textarea>`、`<option>` 这样的表单组件不同于其他原生组件,因为他们可以通过用户交互发生变化。这些组件提供的界面使响应用户交互的表单数据处理更加容易。
|
||||
|
||||
关于 `<form>` 事件详情请查看 [表单事件](/react/docs/events-zh-CN.html#form-events)。
|
||||
关于 `<form>` 事件详情请查看 [表单事件](/react/docs/events-zh-CN.html#表单事件)。
|
||||
|
||||
## 交互属性
|
||||
|
||||
|
||||
@@ -6,18 +6,18 @@ prev: working-with-the-browser-ko-KR.html
|
||||
next: tooling-integration-ko-KR.html
|
||||
---
|
||||
컴포넌트를 빌드한 후에는 `render()`에서 반환된 컴포넌트 인스턴스에 접근하거나 메소드를 호출할 방법이 필요할 수도 있습니다. 반응적 데이터 플로우가 `render()`의 결과물에서 최신의 `props`가 각각의 자식으로 보내진 것을 항상 보장하기 때문에 애플리케이션의 데이터 플로우를 만드는데 대체로 이런 작업은 필요가 없지만, 여전히 이런 작업이 필요하거나 유리한 경우가 있긴 합니다. React는 이를 위해 `refs`라는 탈출구를 제공합니다. `refs`(레퍼런스)는 특히 다음과 같은 경우 유용합니다: 컴포넌트에 의해 렌더된 DOM 마크업을 찾을때 (인스턴스내의 절대적인 위치), 큰 프로젝트의 일부에 React 컴포넌트를 사용하는 경우 또는 기존의 코드베이스를 React로 변경하는 경우.
|
||||
|
||||
|
||||
ref를 어떻게 얻는지 살펴보고, 예제를 완성해 봅시다.
|
||||
|
||||
## ReactDOM.render에서 반환된 ref
|
||||
|
||||
컴포넌트에서 정의한, 가상의 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`을 반환하죠.
|
||||
컴포넌트에서 정의한, 가상의 DOM 엘리먼트를 반환하는 `render()`와 헷갈리지 않도록 합니다. [ReactDOM.render()](/react/docs/top-level-api-ko-KR.html#reactdom.render)는 컴포넌트의 **지원 인스턴스(backing instance)**에 대한 참조를 반환 합니다. [상태를 가지지 않는 컴포넌트](/react/docs/reusable-components-ko-KR.html#상태를-가지지-않는-함수)에 대해선 `null`을 반환하죠.
|
||||
|
||||
|
||||
```js
|
||||
var myComponent = ReactDOM.render(<MyComponent />, myContainer);
|
||||
```
|
||||
|
||||
|
||||
명심하세요. 위의 코드는 컴포넌트 인스턴스를 반환하지 않습니다! 이는 그저 **ReactElement**:React에 마운트된 컴포넌트가 어떻게 보여야 할지 알려주는 경량의 표상(representation) 입니다.
|
||||
|
||||
```js
|
||||
@@ -34,10 +34,10 @@ myComponentInstance.doSomething();
|
||||
> 이는 오직 최상위 레벨에서만 사용되어야 합니다. 컴포넌트의 내부에서는 `props`와 `state`가 자식 컴포넌트와 통신하도록 하거나 문자열이나 콜백 어트리뷰트 등 ref를 얻어오는 다른 방법을 사용하도록 하세요.
|
||||
|
||||
## ref 콜백 어트리뷰트
|
||||
|
||||
|
||||
React는 어떤 컴포넌트에든 추가할 수 있는 특별한 어트리뷰트를 제공합니다. `ref` 어트리뷰트는 콜백 함수일 수 있으며 이는 컴포넌트가 마운트 된 후 즉시 실행됩니다. 참조된 컴포넌트는 파라미터로 전달될 것이며 콜백 함수는 즉시, 혹은 미래에 사용하기 위해 컴포넌트의 참조를 저장합니다.
|
||||
|
||||
`render`에서 반환되는 무엇에든 `ref` 어트리뷰트를 추가하는 것은 간단합니다:
|
||||
`render`에서 반환되는 무엇에든 `ref` 어트리뷰트를 추가하는 것은 간단합니다:
|
||||
|
||||
```js
|
||||
render: function() {
|
||||
@@ -95,7 +95,7 @@ var MyComponent = React.createClass({
|
||||
this.myTextInput.focus();
|
||||
},
|
||||
render: function() {
|
||||
// ref 어트리뷰트는 컴포넌트가 마운트되면
|
||||
// ref 어트리뷰트는 컴포넌트가 마운트되면
|
||||
// this.refs에 컴포넌트에 대한 참조를 추가합니다.
|
||||
return (
|
||||
<div>
|
||||
@@ -119,7 +119,7 @@ ReactDOM.render(
|
||||
이 예제에서, 텍스트 인풋의 **지원 인스턴스**에 대한 참조를 얻었으며 버튼이 클릭되었을때 `focus()`를 호출했습니다.
|
||||
|
||||
합성 컴포넌트에서는 참조는 컴포넌트 클래스의 인스턴스를 가리키기 때문에 클래스에 정의된 어떤 메소드도 호출할 수 있습니다. 컴포넌트의 기저에 있는 DOM 노드에 접근하기 위해서는 [ReactDOM.findDOMNode](/react/docs/top-level-api-ko-KR.html#reactdom.finddomnode)를 "탈출구"로 사용할 수 있습니다. 하지만 이는 캡슐화를 깨며, 대부분의 경우 React 모델을 이용해 더 명확한 방법으로 구조를 짤 수 있기 때문에 추천하지 않습니다.
|
||||
|
||||
|
||||
|
||||
## 요약
|
||||
|
||||
@@ -136,4 +136,4 @@ Refs는 반응적인 `props`와 `state` 스트리밍을 통해서는 불편했
|
||||
- 컴포넌트의 렌더 메소드에서는, 혹은 컴포넌트의 렌더 메소드가 콜스택 어디에서든 실행되는 동안에는 절대 접근하지 마세요.
|
||||
- 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를 조합 컴포넌트에 붙일 수 있습니다.
|
||||
- Refs는 [상태를 가지지 않는 함수](/react/docs/reusable-components-ko-KR.html#상태를-가지지-않는-함수)에 붙일 수 없습니다. 왜냐하면 컴포넌트가 내부 인스턴스를 가지지 않기 때문입니다. 상태를 가지지 않는 컴포넌트는 항상 일반 컴포넌트로 감싸 ref를 조합 컴포넌트에 붙일 수 있습니다.
|
||||
|
||||
@@ -27,11 +27,11 @@ ReactDOM.render(
|
||||
```
|
||||
|
||||
Configure [babel](https://babeljs.io/) with a `.babelrc` file:
|
||||
|
||||
|
||||
```json
|
||||
{ "presets": ["react"] }
|
||||
```
|
||||
|
||||
|
||||
> Note:
|
||||
>
|
||||
> If you are using ES2015, you will want to also use the `babel-preset-es2015` package.
|
||||
@@ -67,26 +67,23 @@ new webpack.DefinePlugin({
|
||||
|
||||
Update your HTML file as below:
|
||||
|
||||
```html{8,12}
|
||||
```html{9}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<script src="build/react-dom.js"></script>
|
||||
<!-- No need for Babel! -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
<script src="build/helloworld.js"></script>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Using React from Bower
|
||||
|
||||
Bower is a package manager optimized for the front-end development. If multiple packages depend on a package - jQuery for example - Bower will download jQuery just once. This is known as a flat dependency graph and it helps reduce page load. For more info, visit http://bower.io/
|
||||
Bower is a package manager optimized for the front-end development. If multiple packages depend on a package - jQuery for example - Bower will download jQuery just once. This is known as a flat dependency graph and it helps reduce page load. For more info, visit [http://bower.io/](http://bower.io/).
|
||||
|
||||
If you'd like to use bower, it's as easy as:
|
||||
|
||||
@@ -96,16 +93,13 @@ bower install --save react
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
|
||||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React!</title>
|
||||
<script src="bower_components/react/react.js"></script>
|
||||
<script src="bower_components/react/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
@@ -123,4 +117,3 @@ bower install --save react
|
||||
## Using master
|
||||
|
||||
We have instructions for building from `master` [in our GitHub repository](https://github.com/facebook/react).
|
||||
|
||||
|
||||
@@ -44,7 +44,10 @@ 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>
|
||||
@@ -89,7 +92,10 @@ Ti accorgerai che la durata delle animazioni devono essere specificate sia nel C
|
||||
```javascript{3-5}
|
||||
render: function() {
|
||||
return (
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}>
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="example"
|
||||
transitionAppear={true}
|
||||
transitionAppearTimeout={500}>
|
||||
<h1>Dissolvenza al Montaggio Iniziale</h1>
|
||||
</ReactCSSTransitionGroup>
|
||||
);
|
||||
@@ -182,7 +188,10 @@ var ImageCarousel = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ReactCSSTransitionGroup transitionName="carousel" transitionEnterTimeout={300} transitionLeaveTimeout={300}>
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="carousel"
|
||||
transitionEnterTimeout={300}
|
||||
transitionLeaveTimeout={300}>
|
||||
<img src={this.props.imageSrc} key={this.props.imageSrc} />
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,10 @@ 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>
|
||||
@@ -90,7 +93,10 @@ 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>
|
||||
);
|
||||
@@ -117,7 +123,7 @@ var TodoList = React.createClass({
|
||||
|
||||
### アニメーショングループを動かすためには、マウントされている必要があります
|
||||
|
||||
子要素にトランジションを適用するためには、 `ReactCSSTransitionGroup` はすでにDOMにマウントされているか、 `transitionAppear` プロパティに `true` がセットされている必要があります。以下の例は動きません。 `ReactCSSTransitionGroup` が新しいアイテムとともにマウントされており、新しいマウントがマウントされていないからです。これと上の[はじめに](#getting-started) とで違いを比較してみてください。
|
||||
子要素にトランジションを適用するためには、 `ReactCSSTransitionGroup` はすでにDOMにマウントされているか、 `transitionAppear` プロパティに `true` がセットされている必要があります。以下の例は動きません。 `ReactCSSTransitionGroup` が新しいアイテムとともにマウントされており、新しいマウントがマウントされていないからです。これと上の[はじめに](#はじめに) とで違いを比較してみてください。
|
||||
|
||||
```javascript{12-15}
|
||||
render: function() {
|
||||
@@ -153,7 +159,10 @@ 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>
|
||||
|
||||
@@ -12,7 +12,6 @@ React에는 애니메이션을 위한 저 수준 API로 `ReactTransitionGroup`
|
||||
|
||||
`ReactCSSTransitionGroup`는 `ReactTransitionGroup`를 기반으로 React 컴포넌트가 DOM에 들어가거나 나올때의 CSS의 트랜지션과 애니메이션을 구현하기 쉽게합니다. 이는 [ng-animate](http://www.nganimate.org/) 라이브러리에 영향을 받았습니다.
|
||||
|
||||
<a name="getting-stared"></a>
|
||||
### 시작하기
|
||||
|
||||
`ReactCSSTransitionGroup`은 `ReactTransitions`을 위한 인터페이스입니다. 이는 애니메이션을 제어할 모든 컴포넌트를 감싸는 하나의 엘리먼트 입니다. 아래는 목록의 아이템을 페이드 인/아웃하는 간단한 예제입니다.
|
||||
@@ -45,7 +44,10 @@ 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>
|
||||
@@ -56,7 +58,7 @@ 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#동적-자식)를 반드시 만들어야 합니다. 한 아이템을 렌더할 때도 예외는 아닙니다. 키는 React가 어떤 자식이 들어오고, 나가고, 머무르는지 파악할 때 사용합니다.
|
||||
|
||||
이 컴포넌트에서 새로운 아이템이 `ReactCSSTransitionGroup`에 추가되면 `example-enter` 아이템은 CSS 클래스를 가지게 되고 다음 순간에 `example-enter-active` CSS 클래스가 추가됩니다. 이는 `transitionName` prop을 기반으로 한 관례입니다.
|
||||
|
||||
@@ -91,7 +93,10 @@ var TodoList = React.createClass({
|
||||
```javascript{3-5}
|
||||
render: function() {
|
||||
return (
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}>
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="example"
|
||||
transitionAppear={true}
|
||||
transitionAppearTimeout={500}>
|
||||
<h1>Fading at Initial Mount</h1>
|
||||
</ReactCSSTransitionGroup>
|
||||
);
|
||||
@@ -148,7 +153,7 @@ var TodoList = React.createClass({
|
||||
|
||||
### 애니메이션 그룹이 작동하려면 마운트가 필요
|
||||
|
||||
자식들에게 트랜지션을 적용하려면 `ReactCSSTransitionGroup`은 이미 DOM에 마운트되어 있거나 prop `transitionAppear`가 `true`로 설정되어야만 합니다. 예를 들어, 밑의 코드는 동작하지 않을 것입니다. 왜냐하면 `ReactCSSTransitionGroup` 안에서 새 아이템을 마운트하는 대신 새 아이템과 같이 `ReactCSSTransitionGroup`를 마운트했기 때문입니다. 이 것을 위에 있는 [시작하기](#getting-stared) 항목과 비교해보세요.
|
||||
자식들에게 트랜지션을 적용하려면 `ReactCSSTransitionGroup`은 이미 DOM에 마운트되어 있거나 prop `transitionAppear`가 `true`로 설정되어야만 합니다. 예를 들어, 밑의 코드는 동작하지 않을 것입니다. 왜냐하면 `ReactCSSTransitionGroup` 안에서 새 아이템을 마운트하는 대신 새 아이템과 같이 `ReactCSSTransitionGroup`를 마운트했기 때문입니다. 이 것을 위에 있는 [시작하기](#시작하기) 항목과 비교해보세요.
|
||||
|
||||
```javascript{12-15}
|
||||
render: function() {
|
||||
@@ -184,7 +189,10 @@ var ImageCarousel = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ReactCSSTransitionGroup transitionName="carousel" transitionEnterTimeout={300} transitionLeaveTimeout={300}>
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="carousel"
|
||||
transitionEnterTimeout={300}
|
||||
transitionLeaveTimeout={300}>
|
||||
<img src={this.props.imageSrc} key={this.props.imageSrc} />
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,10 @@ 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>
|
||||
@@ -90,7 +93,10 @@ You'll notice that animation durations need to be specified in both the CSS and
|
||||
```javascript{3-5}
|
||||
render: function() {
|
||||
return (
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}>
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="example"
|
||||
transitionAppear={true}
|
||||
transitionAppearTimeout={500}>
|
||||
<h1>Fading at Initial Mount</h1>
|
||||
</ReactCSSTransitionGroup>
|
||||
);
|
||||
@@ -183,7 +189,10 @@ var ImageCarousel = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ReactCSSTransitionGroup transitionName="carousel" transitionEnterTimeout={300} transitionLeaveTimeout={300}>
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="carousel"
|
||||
transitionEnterTimeout={300}
|
||||
transitionLeaveTimeout={300}>
|
||||
<img src={this.props.imageSrc} key={this.props.imageSrc} />
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,10 @@ 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>
|
||||
@@ -89,7 +92,10 @@ var TodoList = React.createClass({
|
||||
```javascript{3-5}
|
||||
render: function() {
|
||||
return (
|
||||
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}>
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="example"
|
||||
transitionAppear={true}
|
||||
transitionAppearTimeout={500}>
|
||||
<h1>Fading at Initial Mount</h1>
|
||||
</ReactCSSTransitionGroup>
|
||||
);
|
||||
@@ -182,7 +188,10 @@ var ImageCarousel = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ReactCSSTransitionGroup transitionName="carousel" transitionEnterTimeout={300} transitionLeaveTimeout={300}>
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="carousel"
|
||||
transitionEnterTimeout={300}
|
||||
transitionLeaveTimeout={300}>
|
||||
<img src={this.props.imageSrc} key={this.props.imageSrc} />
|
||||
</ReactCSSTransitionGroup>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
内部で、このミックスインは[shouldComponentUpdate](/react/docs/component-specs-ja-JP.html#updating-shouldcomponentupdate)を実行します。現在のpropsとstateを次のものと比較し、同様のものであれば、 `false` を返します。
|
||||
内部で、このミックスインは[shouldComponentUpdate](/react/docs/component-specs.html#updating-shouldcomponentupdate)を実行します。現在のpropsとstateを次のものと比較し、同様のものであれば、 `false` を返します。
|
||||
|
||||
> 注意:
|
||||
> このミックスインはオブジェクトの比較のみを行います。それらが複雑なデータ構造を持っていた場合、深い位置における違いは見逃されることがあります。単純なpropsやstateをコンポーネントが持っている場合にのみ、使用してください。深いデータ構造が変更されることが分かっている場合は、 `forceUpdate()` を使用してください。または、ネストされたデータの比較を速く行うために[不変オブジェクト](https://facebook.github.io/immutable-js/)の使用を考えてみてください。
|
||||
|
||||
@@ -21,7 +21,7 @@ React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
내부적으로 믹스인은 현재의 props와 state를 다음 값과 비교하여 같다면 `false`를 반환하도록 [shouldComponentUpdate](/react/docs/component-specs-ko-KR.html#updating-shouldcomponentupdate)를 구현합니다.
|
||||
내부적으로 믹스인은 현재의 props와 state를 다음 값과 비교하여 같다면 `false`를 반환하도록 [shouldComponentUpdate](/react/docs/component-specs-ko-KR.html#업데이트-시-shouldcomponentupdate)를 구현합니다.
|
||||
|
||||
> 주의:
|
||||
>
|
||||
|
||||
@@ -6,7 +6,7 @@ prev: pure-render-mixin-ja-JP.html
|
||||
next: advanced-performance-ja-JP.html
|
||||
---
|
||||
|
||||
Reactは普通、従来の枠を超えてとても速いです。しかし、アプリケーションにおいて、少しでもパフォーマンスを上げようという状況では、Reactの差分を取るアルゴリズムを最大限活用するヒントが得られる、[shouldComponentUpdate](/react/docs/component-specs-ja-JP.html#updating-shouldcomponentupdate)のフックを提供します。
|
||||
Reactは普通、従来の枠を超えてとても速いです。しかし、アプリケーションにおいて、少しでもパフォーマンスを上げようという状況では、Reactの差分を取るアルゴリズムを最大限活用するヒントが得られる、[shouldComponentUpdate](/react/docs/component-specs.html#updating-shouldcomponentupdate)のフックを提供します。
|
||||
|
||||
アプリケーション全体のパフォーマンスについての要約を得ることに加えて、ReactPerfはそれらのフックを実際にはどこに配置する必要があるか教えてくれるプロファイリングツールでもあります。
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ prev: pure-render-mixin-ko-KR.html
|
||||
next: advanced-performance-ko-KR.html
|
||||
---
|
||||
|
||||
React는 보통 처음에는 꽤 빠릅니다. 하지만 모든 성능을 짜내야 하는 상황일 때를 위해, React는 [shouldComponentUpdate](/react/docs/component-specs.html#updating-shouldcomponentupdate) 훅을 제공해 React의 diff 알고리즘을 위한 최적화 힌트를 추가할 수 있습니다.
|
||||
React는 보통 처음에는 꽤 빠릅니다. 하지만 모든 성능을 짜내야 하는 상황일 때를 위해, React는 [shouldComponentUpdate](/react/docs/component-specs-ko-KR.html#업데이트-시-shouldcomponentupdate) 훅을 제공해 React의 diff 알고리즘을 위한 최적화 힌트를 추가할 수 있습니다.
|
||||
|
||||
덧붙여 앱의 전반적인 성능의 개요도 제공합니다. ReactPerf는 프로파일링 도구로 정확히 어디에 훅이 필요한지 알려줍니다.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ One of the first questions people ask when considering React for a project is wh
|
||||
|
||||
## Use the production build
|
||||
|
||||
If you're benchmarking or seeing performance problems in your React apps, make sure you're testing with the [minified production build](/react/downloads.html). The development build includes extra warnings that are helpful when building your apps, but it is slower due to the extra bookkeeping it does.
|
||||
If you're benchmarking or experiencing performance problems in your React apps, make sure you're testing with the [minified production build](/react/downloads.html). The development build includes extra warnings that are helpful when building your apps, but it is slower due to the extra bookkeeping it does.
|
||||
|
||||
## Avoiding reconciling the DOM
|
||||
|
||||
|
||||
212
docs/docs/11-advanced-performance.zh-CN.md
Normal file
212
docs/docs/11-advanced-performance.zh-CN.md
Normal file
@@ -0,0 +1,212 @@
|
||||
---
|
||||
id: advanced-performance-zh-CN
|
||||
title: 提高性能
|
||||
permalink: docs/advanced-performance-zh-CN.html
|
||||
prev: shallow-compare-zh-CN.html
|
||||
next: context-zh-CN.html
|
||||
---
|
||||
|
||||
当人们考虑将React应用到自己的系统里时,都会想知道React是否可以和非React的应用一样可以快速的响应各种用户的操作。改变组件的state时,它会重新渲染组件的所有子节点,有人会怀疑这种重新渲染会带来很大的性能开销。但是React使用很多技术来最小化的减少DOM操作的开销达到更新UI的效果。
|
||||
|
||||
## 使用生产构建版本
|
||||
|
||||
如果你在开发React应用中,遇到了一些性能上的问题,你可以使用了[minified production build](/react/downloads.html)进行测试。这个开发构建版本包括了额外的一些警告信息,可以帮助你更好的调试你的应用。由于它做了很多额外的开销,所以它运行起来会相对要慢一点。
|
||||
|
||||
## 避免调整真实DOM树
|
||||
|
||||
React利用*虚拟DOM*,来描述在浏览器上显示的真实DOM树。这种并行的表示方法,可以让React避免直接去操作DOM节点,毕竟操作DOM节点的开销要远远大于直接去操作Javascript的对象。当组件的state或者props更新的时候,React会根据新生成的虚拟DOM和之前的虚拟DOM进行比较,来判断是否需要去更新真实DOM上的内容。只有在前后虚拟DOM不相等的情况下,React才会去[调整](/react/docs/reconciliation.html)真实DOM的结构。
|
||||
|
||||
在此之上,React提供了一个组件生命周期函数`shouldComponentUpdate`,它会在组件进行重渲染过程开始的时候(虚拟DOM和真实DOM进行对比)进行调用。让开发者可以短接这个过程。该函数默认会返回`true`,让React去执行更新。
|
||||
|
||||
```javascript
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
记住一点,在React中,这个函数调用的非常频繁,所以里面的操作不能太复杂,一定要快。
|
||||
|
||||
你有几个聊天对话的消息应用程序。假设只有一个对话改变了。如果你在`ChatThread`组件中实现了`shouldComponentUpdate`函数,React可以跳过对其他线程的重渲染的步骤。
|
||||
|
||||
```javascript
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
// TODO: return whether or not current chat thread is
|
||||
// different to former one.
|
||||
}
|
||||
```
|
||||
|
||||
所以,总而言之,React可以让开发者使用`shouldComponentUpdate`函数来减少对DOM子树的调整,对于那些需要更新的组件,再进行虚拟DOMs的对比。
|
||||
|
||||
## shouldComponentUpdate 实战
|
||||
|
||||
这个一个组件的子树的结构。每一个节点表示`shouldComponentUpdate` return了什么,以及是否虚拟DOMs是相等的。最后,圆的颜色代表这个节点是否需要被重新调整。
|
||||
|
||||
<figure><img src="/react/img/docs/should-component-update.png" /></figure>
|
||||
|
||||
在上述例子中,C2节点的`shouldComponentUpdate`函数返回了`false`,所以React就不需要在这里产生新的虚拟DOM,也就不需要重新调整DOM。由于父节点C2已经在`shouldComponentUpdate`函数中返回`false`,所以它的所有子节点也就不会执行该函数。
|
||||
|
||||
对于C1和C3,`shouldComponentUpdate`函数返回了`true`,React会从上往下对子节点进行检查。对于C6节点,它返回了`true`;由于前后的虚拟DOMs不相等,所以它不得不调整真实DOM。最后在C8这个有趣的节点上。React会去对比前后虚拟DOM,由于前后是相等的,所以它不是对真实DOM进行调整。
|
||||
|
||||
请注意,React只会对C6进行DOM操作。对于C8,它通过对比虚拟DOMs的方式,避免重新渲染。对于C2的子节点以及C7,通过`shouldComponentUpdate`函数,直接忽略了虚拟DOM比较的过程,提高性能。
|
||||
|
||||
所以,我们应该怎么样来实现`shouldComponentUpdate`方法?举个例子,你有个组件仅仅只渲染一个string的文案:
|
||||
|
||||
```javascript
|
||||
React.createClass({
|
||||
propTypes: {
|
||||
value: React.PropTypes.string.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return <div>{this.props.value}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
我们可以简单的像下面一样实现`shouldComponentUpdate`
|
||||
|
||||
```javascript
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
return this.props.value !== nextProps.value;
|
||||
}
|
||||
```
|
||||
|
||||
目前为止,在props/state上处理简单的的数据结构是非常容易的。基于这种数据类型,我们可以通过mixin的方式把该函数引入到你的所有组件中去。事实上,React官方已经提供了这种方法:[PureRenderMixin](/react/docs/pure-render-mixin.html)。
|
||||
|
||||
但是,如果你的组件使用的在state或者props上使用的是可变的数据结构怎么办?组件里的prop不是以一个string的形式`'bar'`存在,而是以一种Javascript对象的形式包含了一个字符串,类似这样`{ foo: 'bar' }`:
|
||||
|
||||
```javascript
|
||||
React.createClass({
|
||||
propTypes: {
|
||||
value: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return <div>{this.props.value.foo}</div>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
如果是这种情况,按照我们刚才的在`shouldComponentUpdate`的实现的话,是不能达到我们的预期:
|
||||
|
||||
```javascript
|
||||
// assume this.props.value is { foo: 'bar' }
|
||||
// assume nextProps.value is { foo: 'bar' },
|
||||
// but this reference is different to this.props.value
|
||||
this.props.value !== nextProps.value; // true
|
||||
```
|
||||
|
||||
因为props实际上是没有改变的,所以`shouldComponentUpdate`始终会返回`true`。为了解决这个问题,我们也有一个可选的解决方案:
|
||||
|
||||
```javascript
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
return this.props.value.foo !== nextProps.value.foo;
|
||||
}
|
||||
```
|
||||
|
||||
基本上,我们是不会利用这种深度比较去判断是否有属性改变。这样的操作十分损耗性能的,并且非常难扩展。最重要的是,如果我们没有仔细管理对象的引用关系,很可能导致对比不出结果。让我们来看看下面这个组件:
|
||||
|
||||
```javascript
|
||||
React.createClass({
|
||||
getInitialState: function() {
|
||||
return { value: { foo: 'bar' } };
|
||||
},
|
||||
|
||||
onClick: function() {
|
||||
var value = this.state.value;
|
||||
value.foo += 'bar'; // ANTI-PATTERN!
|
||||
this.setState({ value: value });
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<InnerComponent value={this.state.value} />
|
||||
<a onClick={this.onClick}>Click me</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
子组件第一次渲染的时候,组件会收到`{ foo: 'bar' }`作为prop中的value的值。如果用户进行了点击的操作,父组件为更新state,变为`{ value: { foo: 'barbar' } }`,之后会触发子组件的重渲染的过程,子组件会收到新的prop中value的值`{ foo: 'barbar' }`。
|
||||
|
||||
问题在与,因为父子组件共同分享了一个对象的引用,当这个对象在`onClick`函数中进行修改后,子组件的prop也已经改变。所以,当重渲染的过程开始,`shouldComponentUpdate`函数就会被触发,`this.props.value.foo` 与`nextProps.value.foo`会是相等的。因为`this.props.value`和`nextProps.value`指向的是同一个对象。
|
||||
|
||||
因此,我们直接阻止了子组件进行重新渲染,整个UI也就不会把`'bar'`更新为`'barbar'`。
|
||||
|
||||
## 使用Immutable-js
|
||||
|
||||
[Immutable-js](https://github.com/facebook/immutable-js)是一个由Lee Byron编写的Javascript的数据类型库,现在已经被Facebook开源了。它通过 *结构共享* 的方式提供了一个 *持久不可变的* 的集合。让我们来看看这个到底是什么东西。
|
||||
|
||||
* *不可变*:一旦被创建,一个集合不能被其他内容所改变
|
||||
* *持久性*:新的集合可以由之前的集合创建出来,或者由一个可变的数据创建。当新的集合被创建出来,原始的集合依然有效。
|
||||
* *结构共享*:新的集合会尽可能的复用之前集合内的内容。减少重复复制来提高性能。如果新集合和原来的集合是相等的,则会直接把之前的集合返回给新集合。
|
||||
|
||||
不可变的特性让跟踪变化变得简单;每次改变总是会产生新的一个对象,所以。我们只需要判断一下它们引用是否相同即可。举个例子,下面是常规的Javascript的写法:
|
||||
|
||||
```javascript
|
||||
var x = { foo: "bar" };
|
||||
var y = x;
|
||||
y.foo = "baz";
|
||||
x === y; // true
|
||||
```
|
||||
|
||||
尽管`y`已经被更改了,但是它的引用还是和`x`是一致的。所以他们两个进行对比,始终会返回`true`。所以,这样的操作应该要用`immutable-js `来完成:
|
||||
|
||||
```javascript
|
||||
var SomeRecord = Immutable.Record({ foo: null });
|
||||
var x = new SomeRecord({ foo: 'bar' });
|
||||
var y = x.set('foo', 'baz');
|
||||
x === y; // false
|
||||
```
|
||||
|
||||
在这样的情况中,当我们改变了x里的内容,会返回给我们一个新的引用,我们可以安全地假定`x`已经改变。
|
||||
|
||||
另一种来跟踪数据变化的方法,是通过 setter 来设置标识符来做脏检查 (dirty checking)。这种方法的问题在于它强迫你使用 setter;你需要多写很多额外代码或者跟踪分析 class 中的数据。另外一种方式是,你可以在更改一个对象之前对它进行一次深复制,之后再进行深比较,来判断这次操作是否造成了数据改变:这种方案的问题在于深复制与深比较都是很昂贵的操作。
|
||||
|
||||
所以,Immutable的数据结构给你提供了一个很方便的方式去跟踪一个对象是否被修改了,我们只需要简单的实现`shouldComponentUpdate`即可。因此,如果我们的props和state模型使用了immutable-js方式,我们可以引入`PureRenderMixin`,从而提高我们的应用的性能。
|
||||
|
||||
## Immutable-js 结合 Flux
|
||||
|
||||
如果你正在使用[Flux](https://facebook.github.io/flux/),你应该在你的stores里使用immutable-js。可以来看下[full API](https://facebook.github.io/immutable-js/docs/#/)。
|
||||
|
||||
让我们看看一种使用Immutable数据结构来处理的方式。首先,我们为每一个入口定义一个`Record`去处理模型。`Record`是一个保存各个字段的一个容器。
|
||||
|
||||
```javascript
|
||||
var User = Immutable.Record({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
email: undefined
|
||||
});
|
||||
|
||||
var Message = Immutable.Record({
|
||||
timestamp: new Date(),
|
||||
sender: undefined,
|
||||
text: ''
|
||||
});
|
||||
```
|
||||
|
||||
Record 函数接受一个对象作为参数;这个对象定义了 Record 中的键值与默认值
|
||||
|
||||
*store*可以用两个list来记录users和messages
|
||||
|
||||
|
||||
```javascript
|
||||
this.users = Immutable.List();
|
||||
this.messages = Immutable.List();
|
||||
```
|
||||
|
||||
它可以很方便的实现处理*payload*数据类型。例如,当一个store收到了新的信息,我们可以直接创建一个新的record,然后把它加到我们message的list中去。
|
||||
|
||||
```javascript
|
||||
this.messages = this.messages.push(new Message({
|
||||
timestamp: payload.timestamp,
|
||||
sender: payload.sender,
|
||||
text: payload.text
|
||||
});
|
||||
```
|
||||
|
||||
注意,因为data的数据结构是不可变的,我们需要重新对`this.message`进行赋值。
|
||||
|
||||
在React方面,如果我们用了 `immutable-js`的数据结构去保存组件的state,我们就可以引入`PureRenderMixin`到所有你的组件中,做一个快速的判断是否需要重新渲染的操作。
|
||||
@@ -32,7 +32,7 @@ Nella directory principale dello starter kit, crea `helloworld.html` con il segu
|
||||
<meta charset="UTF-8" />
|
||||
<title>Ciao React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -32,7 +32,7 @@ React でのハッキングを始めるにあたり、一番簡単なものと
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -59,7 +59,7 @@ $ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<script src="build/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -13,6 +13,11 @@ The easiest way to start hacking on React is using the following JSFiddle Hello
|
||||
* **[React JSFiddle](https://jsfiddle.net/reactjs/69z2wepo/)**
|
||||
* [React JSFiddle without JSX](https://jsfiddle.net/reactjs/5vjqabv3/)
|
||||
|
||||
## Create React App
|
||||
|
||||
**[Create React App](http://github.com/facebookincubator/create-react-app)** is a new officially supported way to create single-page React applications. It offers a modern build setup with no configuration. It requires Node 4 or higher.
|
||||
|
||||
Note that it has [some limitations](https://github.com/facebookincubator/create-react-app#limitations) and is only useful for single-page applications. If you need more flexibility, or if you want to integrate React into an existing project, consider other options below.
|
||||
|
||||
## Starter Pack
|
||||
|
||||
@@ -34,7 +39,7 @@ In the root directory of the starter kit, create a `helloworld.html` with the fo
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<script src="build/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -76,7 +76,7 @@ new webpack.DefinePlugin({
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.js"></script>
|
||||
<script src="build/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
|
||||
@@ -17,7 +17,7 @@ redirect_from: "/docs/reference-ko-KR.html"
|
||||
class Component
|
||||
```
|
||||
|
||||
ES6 클래스 구문을 사용해 React 컴포넌트를 정의했을 때 기본 클래스가 되는 부분입니다. 어떻게 ES6 클래스 구문을 사용해 React를 다루는지는 [재사용가능한 컴포넌트](/react/docs/reusable-components-ko-KR.html#es6-classes)를 확인하세요. 기본 클래스에서 실제 제공되는 메소드들에는 어떤것이 있는지 알아보려면 [컴포넌트 API](/react/docs/component-api-ko-KR.html)를 확인하세요.
|
||||
ES6 클래스 구문을 사용해 React 컴포넌트를 정의했을 때 기본 클래스가 되는 부분입니다. 어떻게 ES6 클래스 구문을 사용해 React를 다루는지는 [재사용가능한 컴포넌트](/react/docs/reusable-components-ko-KR.html#es6-클래스)를 확인하세요. 기본 클래스에서 실제 제공되는 메소드들에는 어떤것이 있는지 알아보려면 [컴포넌트 API](/react/docs/component-api-ko-KR.html)를 확인하세요.
|
||||
|
||||
|
||||
### React.createClass
|
||||
@@ -129,11 +129,11 @@ object React.Children.only(object children)
|
||||
array React.Children.toArray(object children)
|
||||
```
|
||||
|
||||
불투명한 자료구조인 `children`를 개별 자식마다 키를 할당해 평면 배열로 리턴합니다. 이는 render 메소드 내에서 자식의 컬렉션을 조작할 때, 특히 `this.props.children`을 넘기기 전에 재정렬하거나 재단할 때 유용합니다.
|
||||
불투명한 자료구조인 `children`를 개별 자식마다 키를 할당해 평면 배열로 리턴합니다. 이는 render 메소드 내에서 자식의 컬렉션을 조작할 때, 특히 `this.props.children`을 넘기기 전에 재정렬하거나 재단할 때 유용합니다.
|
||||
|
||||
## ReactDOM
|
||||
|
||||
`react-dom` 패키지는 앱의 최상위 레벨에서 사용될 DOM 고유의 메소드를 제공하며, 원한다면 리액트 외부모델을 위한 출구로 사용될 수 있습니다. 대부분의 컴포넌트는 이 모듈을 사용할 필요가 없습니다.
|
||||
`react-dom` 패키지는 앱의 최상위 레벨에서 사용될 DOM 고유의 메소드를 제공하며, 원한다면 리액트 외부모델을 위한 출구로 사용될 수 있습니다. 대부분의 컴포넌트는 이 모듈을 사용할 필요가 없습니다.
|
||||
|
||||
### ReactDOM.render
|
||||
|
||||
@@ -145,7 +145,7 @@ ReactComponent render(
|
||||
)
|
||||
```
|
||||
|
||||
주어진 ReactElement를 `container` 인자에 넘어온 DOM 안에 렌더링하고 컴포넌트의 [레퍼런스](/react/docs/more-about-refs-ko-KR.html)를 컴포넌트에 리턴합니다. [상태가 없는 컴포넌트](/react/docs/reusable-components-ko-KR.html#stateless-functions)에서는 `null`을 리턴합니다.
|
||||
주어진 ReactElement를 `container` 인자에 넘어온 DOM 안에 렌더링하고 컴포넌트의 [레퍼런스](/react/docs/more-about-refs-ko-KR.html)를 컴포넌트에 리턴합니다. [상태가 없는 컴포넌트](/react/docs/reusable-components-ko-KR.html#상태를-가지지-않는-함수)에서는 `null`을 리턴합니다.
|
||||
|
||||
어떤 ReactElement가 이미 `container`에 렌더링 된 적이 있다면, 그것을 업데이트한 뒤 React 컴포넌트의 최신 상태를 반영하기 위해 꼭 필요한 만큼만 DOM을 변경합니다.
|
||||
|
||||
@@ -178,7 +178,7 @@ DOMElement findDOMNode(ReactComponent component)
|
||||
>
|
||||
> `findDOMNode()`는 기본 DOM 노드에 접근하기 위한 출구입니다. 컴포넌트 추상화를 파괴하기 때문에 대부분의 경우 이것의 사용은 권장되지 않습니다.
|
||||
>
|
||||
> `findDOMNode()`는 마운트된 컴포넌트에서만 작동합니다. 이는 컴포넌트가 DOM에 위치해야 함을 뜻합니다. 만약 아직 생성되기전의 컴포넌트에서 `render()`에서 `findDOMNode()`를 호출하는 등 컴포넌트가 마운트 되기 이전에 이를 호출한다면, 예외가 던져질 것입니다.
|
||||
> `findDOMNode()`는 마운트된 컴포넌트에서만 작동합니다. 이는 컴포넌트가 DOM에 위치해야 함을 뜻합니다. 만약 아직 생성되기전의 컴포넌트에서 `render()`에서 `findDOMNode()`를 호출하는 등 컴포넌트가 마운트 되기 이전에 이를 호출한다면, 예외가 던져질 것입니다.
|
||||
>
|
||||
> `findDOMNode()`는 상태가없는 컴포넌트에서 쓸 수 없습니다.
|
||||
|
||||
|
||||
@@ -132,6 +132,10 @@ array React.Children.toArray(object children)
|
||||
|
||||
Return the `children` opaque data structure as a flat array with keys assigned to each child. Useful if you want to manipulate collections of children in your render methods, especially if you want to reorder or slice `this.props.children` before passing it down.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> `React.Children.toArray()` changes keys to preserve the semantics of nested arrays when flattening lists of children. That is, `toArray` prefixes each key in the returned array so that each element's key is scoped to the input array containing it.
|
||||
|
||||
## ReactDOM
|
||||
|
||||
The `react-dom` package provides DOM-specific methods that can be used at the top level of your app and as an escape hatch to get outside of the React model if you need to. Most of your components should not need to use this module.
|
||||
|
||||
@@ -146,7 +146,7 @@ ReactComponent render(
|
||||
)
|
||||
```
|
||||
|
||||
渲染一个 ReactElement 到 DOM 里提供的 `容器(container)`中,并返回一个对 组件(或者返回 `null` 对于 [无状态组件](/react/docs/reusable-components.html#stateless-functions)) 的[引用](/react/docs/more-about-refs.html)
|
||||
渲染一个 ReactElement 到 DOM 里提供的 `容器(container)`中,并返回一个对 组件(或者返回 `null` 对于 [无状态组件](/react/docs/reusable-components-zh-CN.html#无状态函数)) 的[引用](/react/docs/more-about-refs.html)
|
||||
|
||||
如果 ReactElement 之前被渲染到了 `container` 中,这将对它执行一次更新,并仅变动需要变动的 DOM 来反映最新的 React 组件。
|
||||
|
||||
@@ -183,7 +183,7 @@ DOMElement findDOMNode(ReactComponent component)
|
||||
>
|
||||
> `findDOMNode()` 是一个用来访问底层DOM节点的安全舱口.大多数情况下,使用这个安全舱口是不被鼓励的,因为它穿破了组件的抽象.
|
||||
>
|
||||
> `findDOMNode()` 只在已挂载的组件上工作(即是,已经被放置到DOM里的组件).如果你尝试在没有被挂载的组件上调用这个方法(比如在 一个没有被创建的组件的`render()`里 调用 `findDOMNode()` )会抛出一个异常.
|
||||
> `findDOMNode()` 只在已挂载的组件上工作(即是,已经被放置到DOM里的组件).如果你尝试在没有被挂载的组件上调用这个方法(比如在 一个没有被创建的组件的`render()`里 调用 `findDOMNode()` )会抛出一个异常.
|
||||
>
|
||||
> `findDOMNode()` 不能用在无状态组件.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ next: tags-and-attributes-ko-KR.html
|
||||
|
||||
> 주의:
|
||||
>
|
||||
> 그냥 JavaScript 클래스를 컴포넌트 클래스로 사용할 수도 있습니다. 이 클래스는 구현할 수 있는 메소드가 거의 같지만 약간의 차이가 있습니다. 차이에 관한 더 자세한 정보는 [ES6 클래스](/react/docs/reusable-components-ko-KR.html#es6-classes)를 읽어보세요.
|
||||
> 그냥 JavaScript 클래스를 컴포넌트 클래스로 사용할 수도 있습니다. 이 클래스는 구현할 수 있는 메소드가 거의 같지만 약간의 차이가 있습니다. 차이에 관한 더 자세한 정보는 [ES6 클래스](/react/docs/reusable-components-ko-KR.html#es6-클래스)를 읽어보세요.
|
||||
|
||||
### render
|
||||
|
||||
@@ -98,10 +98,9 @@ MyComponent.customMethod('bar'); // true
|
||||
string displayName
|
||||
```
|
||||
|
||||
`displayName` 문자열은 디버그 메시지에 사용됩니다. JSX는 이 값을 자동으로 설정합니다. [JSX 깊이 알기](/react/docs/jsx-in-depth-ko-KR.html#the-transform)를 참고하세요.
|
||||
`displayName` 문자열은 디버그 메시지에 사용됩니다. JSX는 이 값을 자동으로 설정합니다. [JSX 깊이 알기](/react/docs/jsx-in-depth-ko-KR.html#변환)를 참고하세요.
|
||||
|
||||
|
||||
<a name="lifecycle-methods"></a>
|
||||
## 생명주기 메소드
|
||||
|
||||
컴포넌트의 생명주기에서 특정 시점마다 실행되는 메소드들입니다.
|
||||
@@ -152,7 +151,6 @@ componentWillReceiveProps: function(nextProps) {
|
||||
> `componentWillReceiveState`에 해당하는 메소드는 없습니다. prop이 변할 때 state가 바뀔 수는 있지만, 그 역은 불가능합니다. state의 변화에 따라 작업을 실행해야 하면 `componentWillUpdate`를 사용하세요.
|
||||
|
||||
|
||||
<a name="updating-shouldcomponentupdate"></a>
|
||||
### 업데이트 시: shouldComponentUpdate
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -139,7 +139,6 @@ DOMEventTarget relatedTarget
|
||||
|
||||
이 포커스 이벤트는 폼 엘리먼트뿐만 아니라 모든 React DOM 엘리먼트에서 작동합니다.
|
||||
|
||||
<a name="form-events"></a>
|
||||
### 폼 이벤트
|
||||
|
||||
이벤트 이름:
|
||||
|
||||
@@ -50,8 +50,11 @@ function onClick(event) {
|
||||
console.log(eventType); // => "click"
|
||||
}, 0);
|
||||
|
||||
this.setState({clickEvent: event}); // Won't work. this.state.clickEvent will only contain null values.
|
||||
this.setState({eventType: event.type}); // You can still export event properties.
|
||||
// Won't work. this.state.clickEvent will only contain null values.
|
||||
this.setState({clickEvent: event});
|
||||
|
||||
// You can still export event properties.
|
||||
this.setState({eventType: event.type});
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@ next: reconciliation-ko-KR.html
|
||||
|
||||
[DOM 차이점](/react/docs/dom-differences-ko-KR.html)처럼, React는 DOM에는 존재하지 않는 몇몇 어트리뷰트도 제공합니다.
|
||||
|
||||
- `key`: 선택적인 고유 식별자. 컴포넌트가 `render` 과정에서 섞일 때, diff 알고리즘에 의해 파괴되고, 다시 생성될 수 있습니다. 컴포넌트에 영속적인(persists) 키를 할당하면 컴포넌트가 확실히 유지되게 할 수 있습니다. 더 자세한 것은 [여기](/react/docs/multiple-components-ko-KR.html#dynamic-children)에서 보세요.
|
||||
- `key`: 선택적인 고유 식별자. 컴포넌트가 `render` 과정에서 섞일 때, diff 알고리즘에 의해 파괴되고, 다시 생성될 수 있습니다. 컴포넌트에 영속적인(persists) 키를 할당하면 컴포넌트가 확실히 유지되게 할 수 있습니다. 더 자세한 것은 [여기](/react/docs/multiple-components-ko-KR.html#동적-자식)에서 보세요.
|
||||
- `ref`: [여기](/react/docs/more-about-refs-ko-KR.html)를 보세요.
|
||||
- `dangerouslySetInnerHTML`: 생(raw) HTML을 넣을 수 있게 합니다. 주로 DOM 문자열 관리 라이브러리와의 협력하기 위해 사용합니다. 더 자세한 것은 [여기](/react/tips/dangerously-set-inner-html.html)를 보세요.
|
||||
|
||||
@@ -7,9 +7,9 @@ prev: webcomponents-ko-KR.html
|
||||
|
||||
다음은 React에서 사용되는 용어들로, 이 다섯 가지의 타입을 구별하는 것은 중요합니다.
|
||||
|
||||
- [ReactElement / ReactElement 팩토리](#react-elements)
|
||||
- [ReactNode](#react-nodes)
|
||||
- [ReactComponent / ReactComponent 클래스](#react-components)
|
||||
- [ReactElement / ReactElement 팩토리](#react-엘리먼트)
|
||||
- [ReactNode](#react-노드)
|
||||
- [ReactComponent / ReactComponent 클래스](#react-컴포넌트)
|
||||
|
||||
## React 엘리먼트
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ prev: webcomponents-zh-CN.html
|
||||
|
||||
在 React 的术语中,有五个要重点区分的核心类型:
|
||||
|
||||
- [ReactElement / ReactElement Factory](#react-elements)
|
||||
- [ReactElement / ReactElement Factory](#react-elementsreact-元素)
|
||||
- [ReactNode](#react-nodes)
|
||||
- [ReactComponent / ReactComponent Class](#react-components)
|
||||
|
||||
|
||||
@@ -41,10 +41,11 @@ Per questo tutorial renderemo il tutto il più semplice possibile. Incluso nel p
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
@@ -227,11 +228,11 @@ Per prima cosa, aggiungiamo la libreria di terze parti **marked** alla tua appli
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.6.2/remarkable.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
|
||||
@@ -41,10 +41,12 @@ next: thinking-in-react-ja-JP.html
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
@@ -223,11 +225,11 @@ Markdown はインラインでテキストをフォーマットする簡単な
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Hello React</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.6.2/remarkable.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
|
||||
@@ -41,10 +41,11 @@ next: thinking-in-react-ko-KR.html
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
@@ -230,11 +231,11 @@ Markdown은 텍스트를 포맷팅하는 간단한 방식입니다. 예를 들
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.6.2/remarkable.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
|
||||
@@ -41,11 +41,11 @@ For this tutorial, we're going to make it as easy as possible. Included in the s
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.6.2/remarkable.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
@@ -62,7 +62,7 @@ For the remainder of this tutorial, we'll be writing our JavaScript code in this
|
||||
|
||||
> Note:
|
||||
>
|
||||
> We included jQuery here because we want to simplify the code of our future ajax calls, but it's **NOT** mandatory for React to work.
|
||||
> We included jQuery here because we want to simplify the code of our future AJAX calls, but it's **NOT** mandatory for React to work.
|
||||
|
||||
### Your first component
|
||||
|
||||
@@ -181,7 +181,7 @@ Notice how we're mixing HTML tags and components we've built. HTML components ar
|
||||
|
||||
### Using props
|
||||
|
||||
Let's create the `Comment` component, which will depend on data passed in from its parent. Data passed in from a parent component is available as a 'property' on the child component. These 'properties' are accessed through `this.props`. Using props, we will be able to read the data passed to the `Comment` from the `CommentList`, and render some markup:
|
||||
Let's create the `Comment` component, which will depend on data passed in from its parent, `CommentList`. Data passed in from a parent component is available as a 'property' on the child component. These 'properties' are accessed through `this.props`. Using props, we will be able to read the data passed to the `Comment` from the `CommentList`, and render some markup:
|
||||
|
||||
```javascript
|
||||
// tutorial4.js
|
||||
@@ -219,7 +219,7 @@ var CommentList = React.createClass({
|
||||
});
|
||||
```
|
||||
|
||||
Note that we have passed some data from the parent `CommentList` component to the child `Comment` components. For example, we passed *Pete Hunt* (via an attribute) and *This is one comment* (via an XML-like child node) to the first `Comment`. As noted above, the `Comment` component will access these 'properties' through `this.props.author`, and `this.props.children`.
|
||||
Note that we have passed some data from the parent `CommentList` component to the child `Comment` components. For example, we passed *Pete Hunt* (via the `author` attribute) and *This is one comment* (via an XML-like child node) to the first `Comment`. As noted above, the `Comment` component will access these 'properties' through `this.props.author`, and `this.props.children`.
|
||||
|
||||
### Adding Markdown
|
||||
|
||||
@@ -527,6 +527,8 @@ var CommentForm = React.createClass({
|
||||
|
||||
React attaches event handlers to components using a camelCase naming convention. We attach `onChange` handlers to the two `<input>` elements. Now, as the user enters text into the `<input>` fields, the attached `onChange` callbacks are fired and the `state` of the component is modified. Subsequently, the rendered value of the `input` element will be updated to reflect the current component `state`.
|
||||
|
||||
(The astute reader may be surprised that these event handlers work as described, given that the method references are not explicitly bound to `this`. `React.createClass(...)` [automatically binds](/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation) each method to its component instance, obviating the need for explicit binding.)
|
||||
|
||||
#### Submitting the form
|
||||
|
||||
Let's make the form interactive. When the user submits the form, we should clear it, submit a request to the server, and refresh the list of comments. To start, let's listen for the form's submit event and clear it.
|
||||
|
||||
@@ -41,11 +41,11 @@ next: thinking-in-react-zh-CN.html
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>React Tutorial</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.6.2/remarkable.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
|
||||
<script src="https://unpkg.com/jquery@3.1.0/dist/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/remarkable@1.6.2/dist/remarkable.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
|
||||
@@ -22,38 +22,40 @@ If you're just starting out, make sure to use the development version.
|
||||
## Individual Downloads
|
||||
|
||||
#### React {{site.react_version}} (development)
|
||||
The uncompressed, development version of [react.js](https://fb.me/react-{{site.react_version}}.js) and [react-dom.js](https://fb.me/react-dom-{{site.react_version}}.js) with inline documentation (you need both files).
|
||||
The uncompressed, development version of [react.js](https://unpkg.com/react@{{site.react_version}}/dist/react.js) and [react-dom.js](https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js) with inline documentation (you need both files).
|
||||
|
||||
```html
|
||||
<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://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
```
|
||||
|
||||
#### React {{site.react_version}} (production)
|
||||
The compressed, production version of [react.js](https://fb.me/react-{{site.react_version}}.min.js) and [react-dom.js](https://fb.me/react-dom-{{site.react_version}}.min.js) (you need both).
|
||||
The compressed, production version of [react.js](https://unpkg.com/react@{{site.react_version}}/dist/react.min.js) and [react-dom.js](https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.min.js) (you need both).
|
||||
|
||||
```html
|
||||
<script src="https://fb.me/react-{{site.react_version}}.min.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.min.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.min.js"></script>
|
||||
```
|
||||
|
||||
#### React with Add-Ons {{site.react_version}} (development)
|
||||
The uncompressed, development version of React with [optional add-ons](/react/docs/addons.html).
|
||||
|
||||
```html
|
||||
<script src="https://fb.me/react-with-addons-{{site.react_version}}.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react-with-addons.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
|
||||
```
|
||||
|
||||
#### React with Add-Ons {{site.react_version}} (production)
|
||||
The compressed, production version of React with [optional add-ons](/react/docs/addons.html).
|
||||
|
||||
```html
|
||||
<script src="https://fb.me/react-with-addons-{{site.react_version}}.min.js"></script>
|
||||
<script src="https://fb.me/react-dom-{{site.react_version}}.min.js"></script>
|
||||
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react-with-addons.min.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.min.js"></script>
|
||||
```
|
||||
|
||||
All scripts are also available via [CDNJS](https://cdnjs.com/libraries/react/).
|
||||
> Note:
|
||||
>
|
||||
> We're using [unpkg](https://unpkg.com) to serve these files. This is a free service with the goal to provide a hassle-free CDN for npm package authors. React is also available on other free CDNs including [cdnjs](https://cdnjs.com/libraries/react/) and [jsDelivr](https://www.jsdelivr.com/projects/react). If you have concerns with relying on an external host, we always recommend that you download React and serve it from your own servers.
|
||||
|
||||
## npm
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user