Merge remote-tracking branch 'upstream/15-stable' into 15-dev

This commit is contained in:
Paul O’Shannessy
2016-10-03 15:55:53 -07:00
55 changed files with 1618 additions and 742 deletions
+25
View File
@@ -1,3 +1,28 @@
## 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
+2 -99
View File
@@ -1,102 +1,5 @@
# Contributing to React
React is one of Facebook's first open source projects that is both under very active development and is also being used to ship code to everybody on [facebook.com](https://www.facebook.com). We're still working out the kinks to make contributing to this project as easy and transparent as possible, but we're not quite there yet. Hopefully this document makes the process for contributing clear and answers some questions that you may have.
Want to contribute to React? There are a few things you need to know.
## [Code of Conduct](https://code.facebook.com/codeofconduct)
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read [the full text](https://code.facebook.com/codeofconduct) so that you can understand what actions will and will not be tolerated.
## Our Development Process
Some of the core team will be working directly on GitHub. These changes will be public from the beginning. Other changesets will come via a bridge with Facebook's internal source control. This is a necessity as it allows engineers at Facebook outside of the core team to move fast and contribute from an environment they are comfortable in.
### `master` is unsafe
We will do our best to keep `master` in good shape, with tests passing at all times. But in order to move fast, we will make API changes that your application might not be compatible with. We will do our best to communicate these changes and always version appropriately so you can lock into a specific version if need be.
### Test Suite
Use `grunt test` to run the full test suite with PhantomJS.
This command is just a facade to [Jest](https://facebook.github.io/jest/). You may optionally run `npm install -g jest-cli` and use Jest commands directly to have more control over how tests are executed.
For example, `jest --watch` lets you automatically run the test suite on every file change.
You can also run a subset of tests by passing a prefix to `jest`. For instance, `jest ReactDOMSVG` will only run tests in the files that start with `ReactDOMSVG`, such as `ReactDOMSVG-test.js`.
When you know which tests you want to run, you can achieve a fast feedback loop by using these two features together. For example, `jest ReactDOMSVG --watch` will re-run only the matching tests on every change.
Just make sure to run the whole test suite before submitting a pull request!
### Pull Requests
**Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)
You may also be interested in watching [this short video](https://www.youtube.com/watch?v=wUpPsEcGsg8) (26 mins) which gives an introduction on how to contribute to the React JS project.
The core team will be monitoring for pull requests. When we get one, we'll run some Facebook-specific integration tests on it first. From here, we'll need to get another person to sign off on the changes and then merge the pull request. For API changes we may need to fix internal uses, which could cause some delay. We'll do our best to provide updates and feedback throughout the process.
*Before* submitting a pull request, please make sure the following is done…
1. Fork the repo and create your branch from `master`.
2. If you've added code that should be tested, add tests!
3. If you've changed APIs, update the documentation.
4. Ensure the test suite passes (`grunt test`).
5. Make sure your code lints (`grunt lint`) - we've done our best to make sure these rules match our internal linting guidelines.
6. If you haven't already, complete the CLA.
### Contributor License Agreement (CLA)
In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Facebook open source project, you're good to go. If you are submitting a pull request for the first time, just let us know that you have completed the CLA and we can cross-check with your GitHub username.
[Complete your CLA here.](https://code.facebook.com/cla)
## Bugs
### Where to Find Known Issues
We will be using GitHub Issues for our public bugs. We will keep a close eye on this and try to make it clear when we have an internal fix in progress. Before filing a new task, try to make sure your problem doesn't already exist.
### Reporting New Issues
The best way to get your bug fixed is to provide a reduced test case. jsFiddle, jsBin, and other sites provide a way to give live examples. Those are especially helpful though may not work for `JSX`-based code.
### Security Bugs
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe disclosure of security bugs. With that in mind, please do not file public issues; go through the process outlined on that page.
## How to Get in Touch
* IRC - [#reactjs on freenode](https://webchat.freenode.net/?channels=reactjs)
* Discussion forum - [discuss.reactjs.org](https://discuss.reactjs.org/)
## Meeting Notes
React team meets once a week to discuss the development of React, future plans, and priorities.
You can find the meeting notes in a [dedicated repository](https://github.com/reactjs/core-notes/).
## Style Guide
Our linter will catch most styling issues that may exist in your code.
You can check the status of your code styling by simply running: `grunt lint`
However, there are still some styles that the linter cannot pick up. If you are unsure about something, looking at [Airbnb's Style Guide](https://github.com/airbnb/javascript) will guide you in the right direction.
### Code Conventions
* Use semicolons `;`
* Commas last `,`
* 2 spaces for indentation (no tabs)
* Prefer `'` over `"`
* `'use strict';`
* 80 character line length
* Write "attractive" code
* Do not use the optional parameters of `setTimeout` and `setInterval`
### Documentation
* Do not wrap lines at 80 characters
## License
By contributing to React, you agree that your contributions will be licensed under its BSD license.
We wrote a **[contribution guide](https://facebook.github.io/react/contributing/how-to-contribute.html)** to help you get started.
+8 -45
View File
@@ -35,12 +35,12 @@ The fastest way to get started is to serve JavaScript from a CDN. We're using [u
```html
<!-- The core React library -->
<script src="https://unpkg.com/react@15.3.1/dist/react.js"></script>
<script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
<!-- The ReactDOM Library -->
<script src="https://unpkg.com/react-dom@15.3.1/dist/react-dom.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.1.zip) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
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:
@@ -54,50 +54,17 @@ And it's just as easy with [npm](http://npmjs.com):
npm i --save react
```
## Contribute
## Contributing
The main purpose of this repository is to continue to evolve React core, making it faster and easier to use. If you're interested in helping with that, then keep reading. If you're not interested in helping right now that's ok too. :) Any feedback you have about using React would be greatly appreciated.
The main purpose of this repository is to continue to evolve React core, making it faster and easier to use. If you're interested in helping with that, check out our [contribution guide](https://facebook.github.io/react/contributing/how-to-contribute.html).
### Building Your Copy of React
### [Code of Conduct](https://code.facebook.com/codeofconduct)
The process to build `react.js` is built entirely on top of node.js, using many libraries you may already be familiar with.
#### Prerequisites
* You have `node` installed at v4.0.0+ and `npm` at v2.0.0+.
* You have `gcc` installed or are comfortable installing a compiler if needed. Some of our `npm` dependencies may require a compliation step. On OS X, the Xcode Command Line Tools will cover this. On Ubuntu, `apt-get install build-essential` will install the required packages. Similar commands should work on other Linux distros. Windows will require some additional steps, see the [`node-gyp` installation instructions](https://github.com/nodejs/node-gyp#installation) for details.
* You are familiar with `npm` and know whether or not you need to use `sudo` when installing packages globally.
* You are familiar with `git`.
#### Build
Once you have the repository cloned, building a copy of `react.js` is really easy.
```sh
# grunt-cli is needed by grunt; you might have this installed already
npm install -g grunt-cli
npm install
grunt build
```
At this point, you should now have a `build/` directory populated with everything you need to use React. The examples should all work.
### Grunt
We use grunt to automate many tasks. Run `grunt -h` to see a mostly complete listing. The important ones to know:
```sh
# Build and run tests with PhantomJS
grunt test
# Lint the code with ESLint
grunt lint
# Wipe out build directory
grunt clean
```
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read [the full text](https://code.facebook.com/codeofconduct) so that you can understand what actions will and will not be tolerated.
### Good First Bug
To help you get your feet wet and get you familiar with our contribution process, we have a list of [good first bugs](https://github.com/facebook/react/labels/good%20first%20bug) that contain bugs which are fairly easy to fix. This is a great place to get started.
To help you get your feet wet and get you familiar with our contribution process, we have a list of [good first bugs](https://github.com/facebook/react/labels/good%20first%20bug) that contain bugs which are fairly easy to fix. This is a great place to get started.
### License
@@ -107,9 +74,5 @@ React documentation is [Creative Commons licensed](./LICENSE-docs).
Examples provided in this repository and in the documentation are [separately licensed](./LICENSE-examples).
### More…
There's only so much we can cram in here. To read more about the community and guidelines for submitting pull requests, please read the [Contributing document](CONTRIBUTING.md).
## Troubleshooting
See the [Troubleshooting Guide](https://github.com/facebook/react/wiki/Troubleshooting)
+9 -9
View File
@@ -53,13 +53,13 @@ sass:
gems:
- jekyll-redirect-from
- jekyll-paginate
react_version: 15.3.1
react_version: 15.3.2
react_hashes:
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
dev: bQIyvl+8Ufi5KiKZPG9VItNWmhcAXA1pa5nHIEoBGob+rdbjJnpNV3s288Mz2yZu
prod: drG4TSBgFQ0Hb/A3ynRyFDT22irpJDL+duuxvYD5mkC9adCYDqEwnX13371waqiH
addons_dev: gCLxBq3yes/qREmjcw3Tdk5dUh3iB54huWqgxq1lAJZTYzLahJqEik5ZiVnq9Zt4
addons_prod: pmUKSclxJREtkrfcUJvBYTEoJCvO6Vj5ob8IgPSiIX0G3c4w2dKBJMoGEhlv9Gev
dom_dev: ZzFfcTbsRst34N23lWs6TtlfonXwDgpeALh+ObwYXav5BSo0j7KsaAtcdn+xrnS1
dom_prod: MTxlP+/p3lyvc2+LZc2B5xy5reGwrA80whnflxNc6zPgLUmMvbwUoKy7qorBH+P4
dom_server_dev: jHjmbawtj2AhVuJlmE/O1HXAIbQMzHvoXRZEVdhTSrfJXACRVpZm/BpuAi4K89xn
dom_server_prod: LCYUMPll/9t/UsNa/Q1zfti2awxxiiczBUZcQBdeGACH0sU6BEAllZuGxo5b6/kf
+4 -2
View File
@@ -112,8 +112,6 @@ li {
line-height: 20px;
}
a {
color: $linkColor;
text-decoration: none;
@@ -131,3 +129,7 @@ a {
.center {
text-align: center;
}
input {
font-family: inherit;
}
+4
View File
@@ -1,4 +1,8 @@
- title: Contributing
items:
- id: how-to-contribute
title: How to Contribute
- id: codebase-overview
title: Codebase Overview
- id: design-principles
title: Design Principles
+1 -1
View File
@@ -56,7 +56,7 @@ to the DOM.
> lightweight description of what the DOM should look like.
We call this process **reconciliation**. Check out
[this jsFiddle](http://jsfiddle.net/fv6RD/3/) to see an example of
[this jsFiddle](http://jsfiddle.net/2h6th4ju/) to see an example of
reconciliation in action.
Because this re-render is so fast (around 1ms for TodoMVC), the developer
@@ -0,0 +1,230 @@
---
title: "Our First 50,000 Stars"
author: vjeux
---
Just three and a half years ago we open sourced a little JavaScript library called React. The journey since that day has been incredibly exciting.
## Commemorative T-Shirt
In order to celebrate 50,000 GitHub stars, [Maggie Appleton](http://www.maggieappleton.com/) from [egghead.io](http://egghead.io/) has designed us a special T-shirt, which will be available for purchase from Teespring **only for a week** through Thursday, October 6. Maggie also wrote [a blog post](https://www.behance.net/gallery/43269677/Reacts-50000-Stars-Shirt) showing all the different concepts she came up with before settling on the final design.
<a target="_blank" href="https://teespring.com/react-50000-stars"><img src="/react/img/blog/react-50k-tshirt.jpg" width="650" height="340" alt="React 50k Tshirt" /></a>
The T-shirts are super soft using American Apparel's tri-blend fabric; we also have kids and toddler T-shirts and baby onesies available.
* [Adult T-shirts (straight-cut and fitted)](https://teespring.com/react-50000-stars)
* [Kids T-shirts](https://teespring.com/react-50000-stars-kids)
* [Toddler T-Shirts](https://teespring.com/react-50000-stars-toddler)
* [Baby Onesies](https://teespring.com/react-50000-stars-baby)
Proceeds from the shirts will be donated to [CODE2040](http://www.code2040.org/), a nonprofit that creates access, awareness, and opportunities in technology for underrepresented minorities with a specific focus on Black and Latinx talent.
## Archeology
We've spent a lot of time trying to explain the concepts behind React and the problems it attempts to solve, but we haven't talked much about how React evolved before being open sourced. This milestone seemed like as good a time as any to dig through the earliest commits and share some of the more important moments and fun facts.
The story begins in our ads org, where we were building incredibly sophisticated client side web apps using an internal MVC framework called [BoltJS](http://web.archive.org/web/20130608154901/http://shaneosullivan.github.io/boltjs/intro.html). Here's a sample of what some Bolt code looked like:
```js
var CarView = require('javelin/core').createClass({
name: 'CarView',
extend: require('container').Container,
properties: {
wheels: 4,
},
declare: function() {
return {
childViews: [
{ content: 'I have ' },
{ ref: 'wheelView' },
{ content: ' wheels' }
]
};
},
setWheels: function(wheels) {
this.findRef('wheelView').setContent(wheels);
},
getWheels: function() {
return this.findRef('wheelView').getContent();
},
});
var car = new CarView();
car.setWheels(3);
car.placeIn(document.body);
//<div>
// <div>I have </div>
// <div>3</div>
// <div> wheels</div>
//</div>
```
Bolt introduced a number of APIs and features that would eventually make their way into React including `render`, `createClass`, and `refs`. Bolt introduced the concept of `refs` as a way to create references to nodes that can be used imperatively. This was relevant for legacy interoperability and incremental adoption, and while React would eventually strive to be a lot more functional, `refs` proved to be a very useful way to break out of the functional paradigm when the need arose.
But as our applications grew more and more sophisticated, our Bolt codebases got pretty complicated. Recognizing some of the framework's shortcomings, [Jordan Walke](https://twitter.com/jordwalke) started experimenting with a side-project called [FaxJS](https://github.com/jordwalke/FaxJs). His goal was to solve many of the same problems as Bolt, but in a very different way. This is actually where most of React's fundamentals were born, including props, state, re-evaluating large portions of the tree to “diff” the UI, server-side rendering, and a basic concept of components.
```js
TestProject.PersonDisplayer = {
structure : function() {
return Div({
classSet: { personDisplayerContainer: true },
titleDiv: Div({
classSet: { personNameTitle: true },
content: this.props.name
}),
nestedAgeDiv: Div({
content: 'Interests: ' + this.props.interests
})
});
}
};
```
## FBolt is Born
Through his FaxJS experiment, Jordan became convinced that functional APIs — which discouraged mutation — offered a better, more scalable way to build user interfaces. He imported his library into Facebook's codebase in March of 2012 and renamed it “FBolt”, signifying an extension of Bolt where components are written in a functional programming style. Or maybe “FBolt” was a nod to FaxJS he didn't tell us! ;)
The interoperability between FBolt and Bolt allowed us to experiment with replacing just one component at a time with more functional component APIs. We could test the waters of this new functional paradigm, without having to go all in. We started with the components that were clearly best expressed functionally and then we would later continue to push the boundaries of what we could express as functions.
Realizing that FBolt wouldn't be a great name for the library when used on its own, Jordan Walke and [Tom Occhino](https://twitter.com/tomocchino) decided on a new name: “React.” After Tom sent out the diff to rename everything to React, Jordan commented:
> Jordan Walke:
I might add for the sake of discussion, that many systems advertise some kind of reactivity, but they usually require that you set up some kind of point-to-point listeners and won't work on structured data. This API reacts to any state or property changes, and works with data of any form (as deeply structured as the graph itself) so I think the name is fitting.
Most of Tom's other commits at the time were on the first version of [GraphiQL](https://github.com/graphql/graphiql), a project which was recently open sourced.
## Adding JSX
Since about 2010 Facebook has been using an extension of PHP called [XHP](https://www.facebook.com/notes/facebook-engineering/xhp-a-new-way-to-write-php/294003943919/), which enables engineers to create UIs using XML literals right inside their PHP code. It was first introduced to help prevent XSS holes but ended up being an excellent way to structure applications with custom components.
```js
final class :a:post extends :x:element {
attribute :a;
protected function render(): XHPRoot {
$anchor = <a>{$this->getChildren()}</a>;
$form = (
<form
method="post"
action={$this->:href}
target={$this->:target}
class="postLink"
>{$anchor}</form>
);
$this->transferAllAttributes($anchor);
return $form;
}
}
```
Before Jordan's work had even made its way into the Facebook codebase, Adam Hupp implemented an XHP-like concept for JavaScript, written in Haskell. This system enabled you to write the following inside a JavaScript file:
```js
function :example:hello(attrib, children) {
return (
<div class="special">
<h1>Hello, World!</h1>
{children}
</div>
);
}
```
It would compile the above into the following normal ES3-compatible JavaScript:
```js
function jsx_example_hello(attrib, children) {
return (
S.create("div", {"class": "special"}, [
S.create("h1", {}, ["Hello, World!"]),
children
]
);
}
```
In this prototype, `S.create` would immediately create and return a DOM node. Most of the conversations on this prototype revolved around the performance characteristics of `innerHTML` versus creating DOM nodes directly. At the time, it would have been less than ideal to push developers universally in the direction of creating DOM nodes directly since it did not perform as well, especially in Firefox and IE. Facebook's then-CTO [Bret Taylor](https://twitter.com/btaylor) chimed in on the discussion at the time in favor of `innerHTML` over `document.createElement`:
> Bret Taylor:
If you are not convinced about innerHTML, here is a small microbenchmark. It is about the same in Chrome. innerHTML is about 30% faster in the latest version of Firefox (much more in previous versions), and about 90% faster in IE8.
This work was eventually abandoned but was revived after React made its way into the codebase. Jordan sidelined the previous performance discussions by introducing the concept of a “Virtual DOM,” though its eventual name didn't exist yet.
> Jordan Walke:
> For the first step, I propose that we do the easiest, yet most general transformation possible. My suggestion is to simply map xml expressions to function call expressions.
>
> - `<x></x>` becomes `x( )`
> - `<x height=12></x>` becomes `x( {height:12} )`
> - `<x> <y> </y> </x>` becomes `x({ childList: [y( )] })`
>
> At this point, JSX doesn't need to know about React - it's just a convenient way to write function calls. Coincidentally, React's primary abstraction is the function. Okay maybe it's not so coincidental ;)
Adam made a very insightful comment, which is now the default way we write lists in React with JSX.
> Adam Hupp:
> I think we should just treat arrays of elements as a frag. This is useful for constructs like:
>
> ```js
<ul>{foo.map(function(i) { return <li>{i.data}</li>; })}</ul>
```
>
> In this case the ul(..) will get a childList with a single child, which is itself a list.
React didn't end up using Adam's implementation directly. Instead, we created JSX by forking [js-xml-literal](https://github.com/laverdet/js-xml-literal), a side project by XHP creator Marcel Laverdet. JSX took its name from js-xml-literal, which Jordan modified to just be syntactic sugar for deeply nested function calls.
## API Churn
During the first year of React, internal adoption was growing quickly but there was quite a lot of churn in the component APIs and naming conventions:
* `project` was renamed to `declare` then to `structure` and finally to `render`.
* `Componentize` was renamed to `createComponent` and finally to `createClass`.
As the project was about to be open sourced, [Lee Byron](https://twitter.com/leeb) sat down with Jordan Walke, Tom Occhino and Sebastian Markbåge in order to refactor, reimplement, and rename one of React's most beloved features the lifecycle API. Lee [came up with a well-designed API](https://gist.github.com/vjeux/f2b015d230cc1ab18ed1df30550495ed) that is still in place today.
* Concepts
* component - a ReactComponent instance
* state - internal state to a component
* props - external state to a component
* markup - the stringy HTML-ish stuff components generate
* DOM - the document and elements within the document
* Actions
* mount - to put a component into a DOM
* initialize - to prepare a component for rendering
* update - a transition of state (and props) resulting a render.
* render - a side-effect-free process to get the representation (markup) of a component.
* validate - make assertions about something created and provided
* destroy - opposite of initialize
* Operands
* create - make a new thing
* get - get an existing thing
* set - merge into existing
* replace - replace existing
* receive - respond to new data
* force - skip checks to do action
* Notifications
* shouldObjectAction
* objectWillAction
* objectDidAction
## Instagram
In 2012, Instagram got acquired by Facebook. [Pete Hunt](https://twitter.com/floydophone), who was working on Facebook photos and videos at the time, joined their newly formed web team. He wanted to build their website completely in React, which was in stark contrast with the incremental adoption model that had been used at Facebook.
To make this happen, React had to be decoupled from Facebook's infrastructure, since Instagram didn't use any of it. This project acted as a forcing function to do the work needed to open source React. In the process, Pete also discovered and promoted a little project called Webpack. He also implemented the `renderToString` primitive which was needed to do server-side rendering.
As we started to prepare for the open source launch, [Maykel Loomans](https://twitter.com/miekd), a designer on Instagram, made a mock of what the website could look like. The header ended up defining the visual identity of React: its logo and the electric blue color!
<center><a target="_blank" href="/react/img/blog/react-50k-mock-full.jpg"><img src="/react/img/blog/react-50k-mock.jpg" width="400" height="410" alt="React website mock" /></a></center>
In its earliest days, React benefitted tremendously from feedback, ideas, and technical contributions of early adopters and collaborators all over the company. While it might look like an overnight success in hindsight, the story of React is actually a great example of how new ideas often need to go through several rounds of refinement, iteration, and course correction over a long period of time before reaching their full potential.
React's approach to building user interfaces with functional programming principles has changed the way we do things in just a few short years. It goes without saying, but React would be nothing without the amazing open source community that's built up around it!
+262
View File
@@ -0,0 +1,262 @@
---
id: codebase-overview
title: Codebase Overview
layout: contributing
permalink: contributing/codebase-overview.html
prev: how-to-contribute.html
next: design-principles.html
---
This section will give you an overview of the React codebase organization, its conventions, and the implementation.
If you want to [contribute to React](/react/contributing/how-to-contribute.html) we hope that this guide will help you feel more comfortable making changes.
We don't necessarily recommend any of these conventions in React apps. Many of them exist for historical reasons and might change with time.
### Custom Module System
At Facebook, internally we use a custom module system called "Haste". It is similar to [CommonJS](https://nodejs.org/docs/latest/api/modules.html) and also uses `require()` but has a few important differences that often confuse outside contributors.
In CommonJS, when you import a module, you need to specify its relative path:
```js
// Importing from the same folder:
var setInnerHTML = require('./setInnerHTML');
// Importing from a different folder:
var setInnerHTML = require('../utils/setInnerHTML');
// Importing from a deeply nested folder:
var setInnerHTML = require('../client/utils/setInnerHTML');
```
However, with Haste **all filenames are globally unique.** In the React codebase, you can import any module from any other module by its name alone:
```js
var setInnerHTML = require('setInnerHTML');
```
Haste was originally developed for giant apps like Facebook. It's easy to move files to different folders and import them without worrying about relative paths. The fuzzy file search in any editor always takes you to the correct place thanks to globally unique names.
React itself was extracted from Facebook codebase and uses Haste for historical reasons. In the future, we will probably [migrate React to use CommonJS or ES Modules](https://github.com/facebook/react/issues/6336) to be more aligned with the community. However this requires changes in Facebook internal infrastructure so it is unlikely to happen very soon.
**Haste will make more sense to you if you remember a few rules:**
* All filenames in the React source code are unique. This is why they're sometimes verbose.
* When you add a new file, make sure you include a [license header](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/client/utils/setInnerHTML.js#L1-L10). You can copy it from any existing file. A license header always includes [a line like this](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/client/utils/setInnerHTML.js#L9). Change it to match the name of the file you created.
* Dont use relative paths when importing. Instead of `require('./setInnerHTML')`, write `require('setInnerHTML')`.
When we compile React for npm, a script copies all the modules into [a single flat directory called `lib`](https://unpkg.com/react@15/lib/) and prepends all `require()` paths with `./`. This way Node, Browserify, Webpack, and other tools can understand React build output without being aware of Haste.
**If you're reading React source on GitHub and want to quickly jump to any file, press "t".**
This is a GitHub shortcut for searching the current repo for fuzzy filename matches. Start typing the name of the file you are looking for, and it will show up as the first match.
### External Dependencies
React has almost no external dependencies. Usually a `require()` points to a file in React's own codebase. However there are a few relatively rare exceptions.
If you see a `require()` that does not correspond to a file in the React repository, you can look in a special repository called [fbjs](https://github.com/facebook/fbjs). For example, `require('warning')` will resolve to the [`warning` module from fbjs](https://github.com/facebook/fbjs/blob/df9047fec0bbd1e64635ae369c045975777cba7c/packages/fbjs/src/__forks__/warning.js).
The [fbjs repository](https://github.com/facebook/fbjs) exists because React shares some small utilities with libraries like [Relay](https://github.com/facebook/relay), and we keep them in sync. We don't depend on equivalent small modules in the Node ecosystem because we want Facebook engineers to be able to make changes to them whenever necessary. None of the utilities inside fbjs are considered to be public API, and they are only intended for use by Facebook projects such as React.
### Top-Level Folders
After cloning the [React repository](https://github.com/facebook/react), you will see a few top-level folders in it:
* [`src`](https://github.com/facebook/react/tree/master/src) is the source code of React. **If your change is related to the code, `src` is where you'll spend most of your time.**
* [`docs`](https://github.com/facebook/react/tree/master/docs) is the React documentation website. When you change APIs, make sure to update the relevant Markdown files.
* [`examples`](https://github.com/facebook/react/tree/master/examples) contains a few small React demos with different build setups.
* [`packages`](https://github.com/facebook/react/tree/master/packages) contains metadata (such as `package.json`) for all packages in the React repository. Nevertheless their source code is still located inside [`src`](https://github.com/facebook/react/tree/master/src).
* `build` is the build output of React. It is not in the repository but it will appear in your React clone after you [build it](/react/contributing/how-to-contribute.html#development-workflow) for the first time.
There are a few other top-level folders but they are mostly used for the tooling and you likely won't ever encounter them when contributing.
### Colocated Tests
We don't have a top-level directory for unit tests. Instead, we put them into a directories called `__tests__` relative to the files that they test.
For example, a test for [`setInnerHTML.js`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/client/utils/setInnerHTML.js) is located in [`__tests__/setInnerHTML-test.js`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/client/utils/__tests__/setInnerHTML-test.js) right next to it.
### Warnings and Invariants
React codebase uses the `warning` module to display warnings:
```js
var warning = require('warning');
warning(
2 + 2 === 4,
'Math is not working today.'
);
```
**The warning is shown when the `warning` condition is `false`.**
One way to think about it is that the condition should reflect the normal situation rather than the exceptional one.
It is a good idea to avoid spamming the console with duplicate warnings:
````js
var warning = require('warning');
var didWarnAboutMath = false;
if (!didWarnAboutMath) {
warning(
2 + 2 === 4,
'Math is not working today.'
);
didWarnAboutMath = true;
}
```
Warnings are only enabled in development. In production, they are completely stripped out. If you need to forbid some code path from executing, use `invariant` module instead:
```js
var invariant = require('invariant');
invariant(
2 + 2 === 4,
'You shall not pass!'
);
```
**The invariant is thrown when the `invariant` condition is `false`.**
"Invariant" is just a way of saying "this condition always holds true". You can think about it as making an assertion.
It is important to keep development and production behavior similar, so `invariant` throws both in development and in production. The error messages are automatically replaced with error codes in production to avoid negatively affecting the byte size.
### Development and Production
You can use `__DEV__` pseudo-global variable in the codebase to guard development-only blocks of code.
It is inlined during the compile step, and turns into `process.env.NODE_ENV !== 'production'` checks in the CommonJS builds.
For standalone builds, it becomes `true` in the unminified build, and gets completely stripped out with the `if` blocks it guards in the minified build.
```js
if (__DEV__) {
// This code will only run in development.
}
```
### Multiple Packages
React is a [monorepo](http://danluu.com/monorepo/). Its repository contains multiple separate packages so that their changes can be coordinated together, and documentation and issues live in one place.
The npm metadata such as `package.json` files is located in the [`packages`](https://github.com/facebook/react/tree/master/packages) top-level folder. However there is almost no real code in it.
For example, [`packages/react/react.js`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/packages/react/react.js) re-exports [`src/isomorphic/React.js`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/isomorphic/React.js), the real npm entry point. Other packages mostly repeat this pattern. All the important code lives in [`src`](https://github.com/facebook/react/tree/master/src).
While the code is separated in the source tree, the exact package boundaries are slightly different for npm packages and standalone browser builds.
### React Core
The "core" of React includes all the [top-level `React` APIs](/react/docs/top-level-api.html#react), for example:
* `React.createElement()`
* `React.createClass()`
* `React.Component`
* `React.Children`
* `React.PropTypes`
**React core only includes the APIs necessary to define components.** It does not include the [reconciliation](/react/docs/reconciliation.html) algorithm or any platform-specific code. It is used both by React DOM and React Native components.
The code for React core is located in [`src/isomorphic`](https://github.com/facebook/react/tree/master/src/isomorphic) in the source tree. It is available on npm as the [`react`](https://www.npmjs.com/package/react) package. The corresponding standalone browser build is called `react.js`, and it exports a global called `React`.
>**Note:**
>
>Until very recently, `react` npm package and `react.js` standalone build contained all React code (including React DOM) rather than just the core. This was done for backwards compatibility and historical reasons. Since React 15.4.0, the core is better separated in the build output.
>
>There is also an additional standalone browser build called `react-with-addons.js` which we will consider separately further below.
### Renderers
React was originally created for the DOM but it was later adapted to also support native platforms with [React Native](http://facebook.github.io/react-native/). This introduced the concept of "renderers" to React internals.
**Renderers manage how a React tree turns into the underlying platform calls.**
Renderers are located in [`src/renderers`](https://github.com/facebook/react/tree/master/src/renderers/):
* [React DOM Renderer](https://github.com/facebook/react/tree/master/src/renderers/dom) renders React components to the DOM. It implements [top-level `ReactDOM` APIs](/react/docs/top-level-api.html#reactdom) and is available as [`react-dom`](https://www.npmjs.com/package/react-dom) npm package. It can also be used as standalone browser bundle called `react-dom.js` that exports a `ReactDOM` global.
* [React Native Renderer](https://github.com/facebook/react/tree/master/src/renderers/native) renders React components to native views. It is used internally by React Native via [`react-native-renderer`](https://www.npmjs.com/package/react-native-renderer) npm package. In the future a copy of it may get checked into the React Native [repository](https://github.com/facebook/react-native) so that React Native can update React at its own pace.
* [React Test Renderer](https://github.com/facebook/react/tree/master/src/renderers/testing) renders React components to JSON trees. It is used by the [Snapshot Testing](https://facebook.github.io/jest/blog/2016/07/27/jest-14.html) feature of [Jest](https://facebook.github.io/jest) and is available as [react-test-renderer](https://www.npmjs.com/package/react-test-renderer) npm package.
The only other officially supported renderer is [`react-art`](https://github.com/reactjs/react-art). To avoid accidentally breaking it as we make changes to React, we checked it in as [`src/renderers/art`](https://github.com/facebook/react/tree/master/src/renderers/art) and run its test suite. Nevertheless its [GitHub repository](https://github.com/reactjs/react-art) still acts as the source of truth.
While it is [technically possible](https://github.com/iamdustan/tiny-react-renderer) to create custom React renderer, this is currently not officially supported. There is no stable public contract for custom renderers yet which is another reason why we keep them all in a single place.
>**Note:**
>
>Technically the [`native`](https://github.com/facebook/react/tree/master/src/renderers/native) renderer is a very thin layer that teaches React to interact with React Native implementation. The real platform-specific code managing the native views lives in the [React Native repository](https://github.com/facebook/react-native) together with its components.
### Reconcilers
Even vastly different renderers like React DOM and React Native need to share a lot of logic. In particular, the [reconciliation](/react/docs/reconciliation.html) algorithm should be as similar as possible so that declarative rendering, custom components, state, lifecycle methods, and refs work consistently across platforms.
To solve this, different renderers share some code between them. We call this part of React a "reconciler". When an update such as `setState()` is scheduled, the reconciler calls `render()` on components in the tree and mounts, updates, or unmounts them.
Reconcilers are not packaged separately because they currently have no public API. Instead, they are exclusively used by renderers such as React DOM and React Native.
### Stack Reconciler
The "stack" reconciler is the one powering all React production code today. It is located in [`src/renderers/shared/stack/reconciler`](https://github.com/facebook/react/tree/master/src/renderers/shared/stack) and is used by both React DOM and React Native.
It is written in an [object-oriented way](https://en.wikipedia.org/wiki/Composite_pattern) and maintains a separate tree of "internal instances" for all React components. The internal instances exist both for user-defined ("composite") and platform-specific ("host") components. The internal instances are inaccessible directly to the user, and their tree is never exposed.
When a component mounts, updates, or unmounts, the stack reconciler calls a method on that internal instance. The methods are called `mountComponent(element)`, `receiveComponent(nextElement)`, and `unmountComponent(element)`.
#### Host Components
Platform-specific ("host") components, such as `<div>` or a `<View>`, run platform-specific code. For example, React DOM instructs the stack reconciler to use [`ReactDOMComponent`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js) to handle [mounting](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js#L517), [updates](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js#L865), and [unmounting](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js#L1140) of DOM components.
Regardless of the platform, both `<div>` and `<View>` handle managing multiple children in a similar way. For convenience, the stack reconciler provides a helper called [`ReactMultiChild`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactMultiChild.js) that both DOM and Native renderers [use](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/dom/shared/ReactDOMComponent.js#L1203).
#### Composite Components
User-defined ("composite") components should behave the same way with all renderers. This is why the stack reconciler provides a shared implementation in [`ReactCompositeComponent`](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js). It is always the same regardless of the renderer.
Composite components also implement [mounting](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js#L181), [updating](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js#L703), and [unmounting](https://github.com/facebook/react/blob/87724bd87506325fcaf2648c70fc1f43411a87be/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js#L524). However, unlike host components, `ReactCompositeComponent` needs to behave differently depending on user's code. This is why it calls methods, such as `render()` and `componentDidMount()`, on the user-supplied class.
During an update, `ReactCompositeComponent` checks whether the `render()` output has a different `type` or `key` than the last time. If neither `type` nor `key` has changed, it delegates the update to the existing child internal instance. Otherwise, it unmounts the old child instance, and mounts a new one. This is described in the [reconciliation algorithm](/react/docs/reconciliation.html).
#### Recursion
During an update, the stack reconciler "drills down" through composite components, runs their `render()` methods, and decides whether to update or replace their single child instance. It executes platform-specific code as it passes through the host components like `<div>` and `<View>`. Host components may have multiple children which are also processed recursively.
It is important to understand that the stack reconciler always processes the component tree synchronously in a single pass. While individual tree branches may [bail out of reconciliation](/react/docs/advanced-performance.html#avoiding-reconciling-the-dom), the stack reconciler can't pause, and so it is suboptimal when the updates are deep and the available CPU time is limited.
### Fiber Reconciler
The "fiber" reconciler is a new effort aiming to resolve the problems inherent in the stack reconciler and fix a few long-standing issues.
It is a complete rewrite of the reconciler, and is currently [in active development](https://github.com/facebook/react/pulls?utf8=%E2%9C%93&q=is%3Apr%20is%3Aopen%20fiber).
Its main goals are:
* Ability to split interruptible work in chunks.
* Ability to prioritize, rebase and reuse work in progress.
* Ability to yield back and forth between parents and children to support layout in React.
* Ability to return multiple elements from `render()`.
* Better support for error boundaries.
You can read more about it in [React Fiber Architecture](https://github.com/acdlite/react-fiber-architecture). At this moment, it is still very experimental, and far from feature parity with the stack reconciler.
Its source code is located in [`src/renderers/shared/fiber`](https://github.com/facebook/react/tree/master/src/renderers/shared/fiber).
### Event System
React implements a synthetic event system which is agnostic of the renderers and works both with React DOM and React Native. Its source code is located in [`src/renderers/shared/stack/event`](https://github.com/facebook/react/tree/master/src/renderers/shared/stack/event).
There is a [video with a deep code dive into it](https://www.youtube.com/watch?v=dRo_egw7tBc) (66 mins).
### Add-ons
Each of the [React add-ons](/react/docs/addons.html) ships as a separate package on npm with a `react-addons-` prefix. Their source is located in [`src/addons`](https://github.com/facebook/react/tree/master/src/addons) with the exception of [`ReactPerf`](https://github.com/facebook/react/blob/master/src/renderers/shared/ReactPerf.js) and [`ReactTestUtils`](https://github.com/facebook/react/blob/master/src/test/ReactTestUtils.js).
Additionally, we provide a standalone build called `react-with-addons.js` which includes React core *and* all add-ons exposed on the `addons` field of the `React` global object.
### What Next?
Learn the [design principles](/react/contributing/design-principles.html) guiding development of React in the next section.
+1 -2
View File
@@ -3,10 +3,9 @@ id: design-principles
title: Design Principles
layout: contributing
permalink: contributing/design-principles.html
prev: codebase-overview.html
---
After using React in a couple of applications, you might be interested in contributing to React. Before [diving into specifics](https://github.com/facebook/react/blob/master/CONTRIBUTING.md), we think it's important to establish a few design principles guiding our decisions about changes in React.
We wrote this document so that you have a better idea of how we decide what React does and what React doesn't do, and what our development philosophy is like. While we are excited to see community contributions, we are not likely to choose a path that violates one or more of these principles.
>**Note:**
+159
View File
@@ -0,0 +1,159 @@
---
id: how-to-contribute
title: How to Contribute
layout: contributing
permalink: contributing/how-to-contribute.html
next: codebase-overview.html
---
React is one of Facebook's first open source projects that is both under very active development and is also being used to ship code to everybody on [facebook.com](https://www.facebook.com). We're still working out the kinks to make contributing to this project as easy and transparent as possible, but we're not quite there yet. Hopefully this document makes the process for contributing clear and answers some questions that you may have.
### [Code of Conduct](https://code.facebook.com/codeofconduct)
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read [the full text](https://code.facebook.com/codeofconduct) so that you can understand what actions will and will not be tolerated.
### Open Development
All work on React happens directly on [GitHub](https://github.com/facebook/react). Both core team members and external contributors send pull requests which go through the same review process.
### Branch Organization
We will do our best to keep the [`master` branch](https://github.com/facebook/react/tree/master) in good shape, with tests passing at all times. But in order to move fast, we will make API changes that your application might not be compatible with. We recommend that you use [the latest stable version of React](/react/downloads.html).
If you send a pull request, please do it against the `master` branch. We maintain stable branches for major versions separately but we don't accept pull requests to them directly. Instead, we cherry-pick non-breaking changes from master to the latest stable major version.
### Semantic Versioning
React follows [semantic versioning](http://semver.org/). We release patch versions for bugfixes, minor versions for new features, and major versions for any breaking changes. When we make breaking changes, we also introduce deprecation warnings in a minor version so that our users learn about the upcoming changes and migrate their code in advance.
We tag every pull request with a label marking whether the change should go in the next [patch](https://github.com/facebook/react/pulls?q=is%3Aopen+is%3Apr+label%3Asemver-patch), [minor](https://github.com/facebook/react/pulls?q=is%3Aopen+is%3Apr+label%3Asemver-minor), or a [major](https://github.com/facebook/react/pulls?q=is%3Aopen+is%3Apr+label%3Asemver-major) version. We release new patch versions every few weeks, minor versions every few months, and major versions one or two times a year.
Every significant change is documented in the [changelog file](https://github.com/facebook/react/blob/master/CHANGELOG.md).
### Bugs
#### Where to Find Known Issues
We are using [GitHub Issues](https://github.com/facebook/react/issues) for our public bugs. We keep a close eye on this and try to make it clear when we have an internal fix in progress. Before filing a new task, try to make sure your problem doesn't already exist.
#### Reporting New Issues
The best way to get your bug fixed is to provide a reduced test case. This [JSFiddle template](https://jsfiddle.net/reactjs/69z2wepo/) is a great starting point.
#### Security Bugs
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe disclosure of security bugs. With that in mind, please do not file public issues; go through the process outlined on that page.
### How to Get in Touch
* IRC: [#reactjs on freenode](https://webchat.freenode.net/?channels=reactjs)
* Discussion forum: [discuss.reactjs.org](https://discuss.reactjs.org/)
There is also [an active community of React users on the Discord chat platform](http://www.reactiflux.com/) in case you need help with React.
### Proposing a Change
If you intend to change to the public API, or make any non-trivial changes to the implementation, we recommend [filing an issue](https://github.com/facebook/react/issues/new). This lets us reach an agreement on your proposal before you put significant effort into it.
If you're only fixing a bug, it's fine to submit a pull request right away but we still recommend to file an issue detailing what you're fixing. This is helpful in case we don't accept that specific fix but want to keep track of the issue.
### Your First Pull Request
Working on your first Pull Request? You can learn how from this free video series:
**[How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)**
To help you get your feet wet and get you familiar with our contribution process, we have a list of **[good first bugs](https://github.com/facebook/react/labels/good%20first%20bug)** that contain bugs which are fairly easy to fix. This is a great place to get started.
If you decide to fix an issue, please be sure to check the comment thread in case somebody is already working on a fix. If nobody is working on it at the moment, please leave a comment stating that you intend to work on it so other people don't accidentally duplicate your effort.
If somebody claims an issue but doesn't follow up for more than two weeks, it's fine to take over it but you should still leave a comment.
### Sending a Pull Request
The core team is monitoring for pull requests. We will review your pull request and either merge it, request changes to it, or close it with an explanation. For API changes we may need to fix our internal uses at Facebook.com, which could cause some delay. We'll do our best to provide updates and feedback throughout the process.
**Before submitting a pull request,** please make sure the following is done:
1. Fork [the repository](https://github.com/facebook/react) and create your branch from `master`.
2. If you've added code that should be tested, add tests!
3. If you've changed APIs, update the documentation.
4. Ensure the test suite passes (`npm test`).
5. Make sure your code lints (`npm run lint`).
6. If you haven't already, complete the CLA.
### Contributor License Agreement (CLA)
In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Facebook open source project, you're good to go. If you are submitting a pull request for the first time, just let us know that you have completed the CLA and we can cross-check with your GitHub username.
**[Complete your CLA here.](https://code.facebook.com/cla)**
### Contribution Prerequisites
* You have `node` installed at v4.0.0+ and `npm` at v2.0.0+.
* You have `gcc` installed or are comfortable installing a compiler if needed. Some of our `npm` dependencies may require a compilation step. On OS X, the Xcode Command Line Tools will cover this. On Ubuntu, `apt-get install build-essential` will install the required packages. Similar commands should work on other Linux distros. Windows will require some additional steps, see the [`node-gyp` installation instructions](https://github.com/nodejs/node-gyp#installation) for details.
* You are familiar with `npm` and know whether or not you need to use `sudo` when installing packages globally.
* You are familiar with `git`.
### Development Workflow
After cloning React, run `npm install` to fetch its dependencies.
Then, you can run several commands:
* `npm run lint` checks the code style.
* `npm test` runs the complete test suite.
* `npm test -- --watch` runs an interactive test watcher.
* `npm test <pattern>` runs tests with matching filenames.
* `npm run build` creates a `build` folder with all the packages.
We recommend running `npm test` (or its variations above) to make sure you don't introduce any regressions as you work on your change. However it can be handy to try your build of React in a real project.
First, run `npm run build`. This will produce pre-built bundles in `build` folder, as well as prepare npm packages inside `build/packages`.
The easiest way to try your changes is to open and modify `examples/basic/index.html`. This file already uses `react.js` from the `build` folder so it will pick up your changes. Please make sure to rollback any unintentional changes in `examples` before sending a pull request.
If you want to try your changes in your existing React project, you may copy `build/react.js`, `build/react-dom.js`, or any other build products into your app and use them instead of the stable version. If your project uses React from npm, you may delete `react` and `react-dom` in its dependencies and use `npm link` to point them to your local `build` folder:
```sh
cd your_project
rm -rf node_modules/react
rm -rf node_modules/react-dom
npm link ~/path_to_your_react_clone/build/packages/react
npm link ~/path_to_your_react_clone/build/packages/react-dom
```
Every time you run `npm run build` in the React folder, the updated versions will appear in your project's `node_modules`. You can then rebuild your project to try your changes.
We still require that your pull request contains unit tests for any new functionality. This way we can ensure that we don't break your code in the future.
### Style Guide
Our linter will catch most styling issues that may exist in your code.
You can check the status of your code styling by simply running `npm run lint`.
However, there are still some styles that the linter cannot pick up. If you are unsure about something, looking at [Airbnb's Style Guide](https://github.com/airbnb/javascript) will guide you in the right direction.
### Code Conventions
* Use semicolons `;`
* Commas last `,`
* 2 spaces for indentation (no tabs)
* Prefer `'` over `"`
* `'use strict';`
* 80 character line length (**except documentation**)
* Write "attractive" code
* Do not use the optional parameters of `setTimeout` and `setInterval`
### License
By contributing to React, you agree that your contributions will be licensed under its BSD license.
### Meeting Notes
React team meets once a week to discuss the development of React, future plans, and priorities. You can find the meeting notes in a [dedicated repository](https://github.com/reactjs/core-notes/).
### What Next?
You may be interested in watching [this short video](https://www.youtube.com/watch?v=wUpPsEcGsg8) (26 mins) which gives an introduction on how to contribute to React.
Read the next sections to learn more about [understanding the codebase](/react/contributing/codebase-overview.html), and the [design principles](/react/contributing/design-principles.html) guiding the development of React.
+7 -5
View File
@@ -36,8 +36,8 @@ Let's look at a really simple example. Create a `hello-react.html` file with the
For the rest of the documentation, we'll just focus on the JavaScript code and assume it's inserted into a template like the one above. Replace the placeholder comment above with the following JSX:
```javascript
var HelloWorld = React.createClass({
render: function() {
class HelloWorld extends React.Component {
render() {
return (
<p>
Hello, <input type="text" placeholder="Your name here" />!
@@ -45,14 +45,16 @@ var HelloWorld = React.createClass({
</p>
);
}
});
}
setInterval(function() {
function tick() {
ReactDOM.render(
<HelloWorld date={new Date()} />,
document.getElementById('example')
);
}, 500);
}
setInterval(tick, 500);
```
## Reactive Updates
+31 -32
View File
@@ -17,8 +17,8 @@ By building modular components that reuse other components with well-defined int
Let's create a simple Avatar component which shows a Facebook page picture and name using the Facebook Graph API.
```javascript
var Avatar = React.createClass({
render: function() {
class Avatar extends React.Component {
render() {
return (
<div>
<PagePic pagename={this.props.pagename} />
@@ -26,25 +26,25 @@ var Avatar = React.createClass({
</div>
);
}
});
}
var PagePic = React.createClass({
render: function() {
class PagePic extends React.Component {
render() {
return (
<img src={'https://graph.facebook.com/' + this.props.pagename + '/picture'} />
);
}
});
}
var PageLink = React.createClass({
render: function() {
class PageLink extends React.Component {
render() {
return (
<a href={'https://www.facebook.com/' + this.props.pagename}>
{this.props.pagename}
</a>
);
}
});
}
ReactDOM.render(
<Avatar pagename="Engineering" />,
@@ -110,13 +110,12 @@ In most cases, this can be sidestepped by hiding elements instead of destroying
The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a `key`:
```javascript
render: function() {
var results = this.props.results;
render() {
return (
<ol>
{results.map(function(result) {
return <li key={result.id}>{result.text}</li>;
})}
{this.props.results.map((result) => (
<li key={result.id}>{result.text}</li>
))}
</ol>
);
}
@@ -128,41 +127,41 @@ The `key` should *always* be supplied directly to the components in the array, n
```javascript
// WRONG!
var ListItemWrapper = React.createClass({
render: function() {
class ListItemWrapper extends React.Component {
render() {
return <li key={this.props.data.id}>{this.props.data.text}</li>;
}
});
var MyComponent = React.createClass({
render: function() {
}
class MyComponent extends React.Component {
render() {
return (
<ul>
{this.props.results.map(function(result) {
return <ListItemWrapper data={result}/>;
})}
{this.props.results.map((result) => (
<ListItemWrapper data={result} />
)}
</ul>
);
}
});
}
```
```javascript
// Correct :)
var ListItemWrapper = React.createClass({
render: function() {
class ListItemWrapper extends React.Component {
render() {
return <li>{this.props.data.text}</li>;
}
});
var MyComponent = React.createClass({
render: function() {
}
class MyComponent extends React.Component {
render() {
return (
<ul>
{this.props.results.map(function(result) {
return <ListItemWrapper key={result.id} data={result}/>;
})}
{this.props.results.map((result) => (
<ListItemWrapper key={result.id} data={result} />
)}
</ul>
);
}
});
}
```
You can also key children by passing a ReactFragment object. See [Keyed Fragments](create-fragment.html) for more details.
+352 -209
View File
@@ -10,90 +10,105 @@ When designing interfaces, break down the common design elements (buttons, form
## Prop Validation
As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify `propTypes`. `React.PropTypes` exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. Note that for performance reasons `propTypes` is only checked in development mode. Here is an example documenting the different validators provided:
As your app grows it's helpful to ensure that your components are used correctly. We do this by allowing you to specify `propTypes`. `React.PropTypes` exports a range of validators that can be used to make sure the data you receive is valid. When an invalid value is provided for a prop, a warning will be shown in the JavaScript console. Note that for performance reasons `propTypes` is only checked in development mode.
You can assign a special property to a component to declare its `propTypes`:
```javascript
React.createClass({
propTypes: {
// You can declare that a prop is a specific JS primitive. By default, these
// are all optional.
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
optionalSymbol: React.PropTypes.symbol,
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: React.PropTypes.node,
Greeting.propTypes = {
name: React.PropTypes.string
};
```
// A React element.
optionalElement: React.PropTypes.element,
Here is an example documenting the different validators provided:
// You can also declare that a prop is an instance of a class. This uses
// JS's instanceof operator.
optionalMessage: React.PropTypes.instanceOf(Message),
```javascript
MyComponent.propTypes = {
// You can declare that a prop is a specific JS primitive. By default, these
// are all optional.
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
optionalSymbol: React.PropTypes.symbol,
// You can ensure that your prop is limited to specific values by treating
// it as an enum.
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: React.PropTypes.node,
// An object that could be one of many types
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// A React element.
optionalElement: React.PropTypes.element,
// An array of a certain type
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// You can also declare that a prop is an instance of a class. This uses
// JS's instanceof operator.
optionalMessage: React.PropTypes.instanceOf(Message),
// An object with property values of a certain type
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
// You can ensure that your prop is limited to specific values by treating
// it as an enum.
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// An object taking on a particular shape
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// An object that could be one of many types
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// You can chain any of the above with `isRequired` to make sure a warning
// is shown if the prop isn't provided.
requiredFunc: React.PropTypes.func.isRequired,
// An array of a certain type
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// A value of any data type
requiredAny: React.PropTypes.any.isRequired,
// An object with property values of a certain type
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
// You can also specify a custom validator. It should return an Error
// object if the validation fails. Don't `console.warn` or throw, as this
// won't work inside `oneOfType`.
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
// An object taking on a particular shape
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// You can also supply a custom validator to `arrayOf` and `objectOf`.
// It should return an Error object if the validation fails. The validator
// will be called for each key in the array or object. The first two
// arguments of the validator are the array or object itself, and the
// current item's key.
customArrayProp: React.PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
})
// You can chain any of the above with `isRequired` to make sure a warning
// is shown if the prop isn't provided.
requiredFunc: React.PropTypes.func.isRequired,
// A value of any data type
requiredAny: React.PropTypes.any.isRequired,
// You can also specify a custom validator. It should return an Error
// object if the validation fails. Don't `console.warn` or throw, as this
// won't work inside `oneOfType`.
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
/* ... */
});
// You can also supply a custom validator to `arrayOf` and `objectOf`.
// It should return an Error object if the validation fails. The validator
// will be called for each key in the array or object. The first two
// arguments of the validator are the array or object itself, and the
// current item's key.
customArrayProp: React.PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
})
};
```
### Single Child
@@ -101,20 +116,21 @@ React.createClass({
With `React.PropTypes.element` you can specify that only a single child can be passed to a component as children.
```javascript
var MyComponent = React.createClass({
propTypes: {
children: React.PropTypes.element.isRequired
},
render: function() {
class MyComponent extends React.Component {
render() {
// This must be exactly one element or it will warn.
var children = this.props.children;
return (
<div>
{this.props.children} // This must be exactly one element or it will warn.
{children}
</div>
);
}
}
});
MyComponent.propTypes = {
children: React.PropTypes.element.isRequired
};
```
## Default Prop Values
@@ -122,29 +138,41 @@ var MyComponent = React.createClass({
React lets you define default values for your `props` in a very declarative way:
```javascript
var ComponentWithDefaultProps = React.createClass({
getDefaultProps: function() {
return {
value: 'default value'
};
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
/* ... */
});
}
// Specifies the default values for props:
Greeting.defaultProps = {
name: 'Stranger'
};
// Renders "Hello, Stranger":
ReactDOM.render(
<Greeting />,
document.getElementById('example')
);
```
The result of `getDefaultProps()` will be cached and used to ensure that `this.props.value` will have a value if it was not specified by the owner component. This allows you to safely just use your props without having to write repetitive and fragile code to handle that yourself.
The `defaultProps` will be used to ensure that `this.props.name` will have a value if it was not specified by the parent component. This allows you to safely just use your props without having to write repetitive and fragile code to handle that yourself.
## Transferring Props: A Shortcut
A common type of React component is one that extends a basic HTML element in a simple way. Often you'll want to copy any HTML attributes passed to your component to the underlying HTML element. To save typing, you can use the JSX _spread_ syntax to achieve this:
```javascript
var CheckLink = React.createClass({
render: function() {
class CheckLink extends React.Component {
render() {
// This takes any props passed to CheckLink and copies them to <a>
return <a {...this.props}>{'√ '}{this.props.children}</a>;
return (
<a {...this.props}>{'√ '}{this.props.children}</a>
);
}
});
}
ReactDOM.render(
<CheckLink href="/checked.html">
@@ -154,9 +182,241 @@ ReactDOM.render(
);
```
## Mixins
## Stateless Functions
Components are the best way to reuse code in React, but sometimes very different components may share some common functionality. These are sometimes called [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). React provides `mixins` to solve this problem.
If a component doesn't use local state or lifecycle hooks, you can define it as a function instead of a class:
```javascript
function Greeting(props) {
return <h1>Hello, {props.name}</h1>;
}
ReactDOM.render(
<Greeting name="Sebastian" />,
document.getElementById('example')
);
```
Or using the new ES6 arrow syntax:
```javascript
const Greeting = (props) => (
<h1>Hello, {props.name}</h1v>
);
ReactDOM.render(
<Greeting name="Sebastian" />,
document.getElementById('example')
);
```
This simplified component API is intended for components that are pure functions of their props. These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate.
However, you may still specify `.propTypes` and `.defaultProps` by setting them as properties on the function, just as you would set them on an ES6 class:
```javascript
function Greeting(props) {
return (
<h1>Hello, {props.name}</h1v>
);
}
Greeting.propTypes = {
name: React.PropTypes.string
};
Greeting.defaultProps = {
name: 'John Doe'
};
ReactDOM.render(
<Greeting name="Mădălina"/>,
document.getElementById('example')
);
```
>**Note:**
>
> Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component. Normally this isn't an issue, since stateless functions do not provide an imperative API. Without an imperative API, there isn't much you could do with an instance anyway. However, if a user wants to find the DOM node of a stateless function component, they must wrap the component in a stateful component (eg. ES6 class component) and attach the ref to the stateful wrapper component.
In an ideal world, many of your components would be stateless functions. In the future we plan to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations.
When you don't need local state or lifecycle hooks in a component, we recommend declaring it with a function. Otherwise, we recommend to use the ES6 class syntax.
## ES6 Classes and React.createClass()
Normally you would define a React component as a plain JavaScript class:
```javascript
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
```
If you don't use ES6 yet, you may use [`React.createClass`](/react/docs/top-level-api.html#react.createclass) helper instead:
```javascript
var Greeting = React.createClass({
render: function() {
return <h1>Hello, {this.props.name}</h1>;
}
});
```
The API of ES6 classes is similar to [`React.createClass`](/react/docs/top-level-api.html#react.createclass) with a few exceptions.
### Declaring Prop Types and Default Props
With functions and ES6 classes, `propTypes` and `defaultProps` are defined as properties on the components themselves:
```javascript
class Greeting extends React.Component {
// ...
}
Greeting.propTypes = {
name: React.PropTypes.string
};
Greeting.defaultProps = {
name: 'Mary'
};
```
With `React.createClass()`, you need to define `propTypes` as a property on the passed object, and `getDefaultProps()` as a function on it:
```javascript
var Greeting = React.createClass({
propTypes: {
name: React.PropTypes.string
},
getDefaultProps: function() {
return {
name: 'Mary'
};
},
// ...
});
```
### Setting the Initial State
In ES6 classes, you can define the initial state by assigning `this.state` in the constructor:
```javascript
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: props.initialCount};
}
// ...
}
```
With `React.createClass()`, you have to provide a separate `getInitialState` method that returns the initial state:
```javascript
var Counter = React.createClass({
getInitialState: function() {
return {count: props.initialCount};
},
// ...
});
```
### Autobinding
In React components declared as ES6 classes, methods follow the same semantics as regular ES6 classes. This means that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` in the constructor:
```javascript
class SayHello extends React.Component {
constructor(props) {
super(props);
// This line is important!
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
alert('Hello!');
}
render() {
// Because we `this.tick` is bound, we can use it as an event handler.
return (
<button onClick={this.handleClick}>
Say hello
</button>
);
}
}
```
With `React.createClass()`, this is not necessary because it binds all methods:
```javascript
var SayHello = React.createClass({
handleClick: function() {
alert('Hello!');
},
render: function() {
return (
<button onClick={this.handleClick}>
Say hello
</button>
);
}
});
```
This means writing ES6 classes comes with a little more boilerplate code for event handlers, but the upside is slightly better performance in large applications.
If the boilerplate code is too unattractive to you, you may enable the **experimental** [Class Properties](https://babeljs.io/docs/plugins/transform-class-properties/) syntax proposal with Babel:
```javascript
class SayHello extends React.Component {
// WARNING: this syntax is experimental!
// Using an arrow here binds the method:
handleClick = () => {
alert('Hello!');
}
render() {
return (
<button onClick={this.handleClick}>
Say hello
</button>
);
}
}
```
Please note that the syntax above is **experimental** and the syntax may change, or the proposal might not make it into the language.
If you'd rather play it safe, you have a few options:
* Bind methods in the constructor.
* Use arrow functions, e.g. `onClick={(e) => this.handleClick(e)})`.
* Keep using `React.createClass()`.
### Mixins
>**Note:**
>
>ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes.
>
>**We also found numerous issues in codebases using mixins, [and don't recommend using them in the new code](/react/blog/2016/07/13/mixins-considered-harmful.html).**
>
>This section exists only for the reference.
Sometimes very different components may share some common functionality. These are sometimes called [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). [`React.createClass`](/react/docs/top-level-api.html#react.createclass) lets you use a legacy `mixins` system for that.
One common use case is a component wanting to update itself on a time interval. It's easy to use `setInterval()`, but it's important to cancel your interval when you don't need it anymore to save memory. React provides [lifecycle methods](/react/docs/working-with-the-browser.html#component-lifecycle) that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy `setInterval()` function that will automatically get cleaned up when your component is destroyed.
@@ -199,121 +459,4 @@ ReactDOM.render(
);
```
A nice feature of mixins is that if a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.
## ES6 Classes
You may also define your React classes as a plain JavaScript class. For example using ES6 class syntax:
```javascript
class HelloMessage extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
```
The API is similar to `React.createClass` with the exception of `getInitialState`. Instead of providing a separate `getInitialState` method, you set up your own `state` property in the constructor. Just like the return value of `getInitialState`, the value you assign to `this.state` will be used as the initial state for your component.
Another difference is that `propTypes` and `defaultProps` are defined as properties on the constructor instead of in the class body.
```javascript
export class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: props.initialCount};
this.tick = this.tick.bind(this);
}
tick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div onClick={this.tick}>
Clicks: {this.state.count}
</div>
);
}
}
Counter.propTypes = { initialCount: React.PropTypes.number };
Counter.defaultProps = { initialCount: 0 };
```
### No Autobinding
Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` or [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `=>`:
```javascript
// You can use bind() to preserve `this`
<div onClick={this.tick.bind(this)}>
// Or you can use arrow functions
<div onClick={() => this.tick()}>
```
We recommend that you bind your event handlers in the constructor so they are only bound once for every instance:
```javascript
constructor(props) {
super(props);
this.state = {count: props.initialCount};
this.tick = this.tick.bind(this);
}
```
Now you can use `this.tick` directly as it was bound once in the constructor:
```javascript
// It is already bound in the constructor
<div onClick={this.tick}>
```
This is better for performance of your application, especially if you implement [shouldComponentUpdate()](/react/docs/component-specs.html#updating-shouldcomponentupdate) with a [shallow comparison](/react/docs/shallow-compare.html) in the child components.
### No Mixins
Unfortunately ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes. Instead, we're working on making it easier to support such use cases without resorting to mixins.
## Stateless Functions
You may also define your React classes as a plain JavaScript function. For example using the stateless function syntax:
```javascript
function HelloMessage(props) {
return <div>Hello {props.name}</div>;
}
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
```
Or using the new ES6 arrow syntax:
```javascript
const HelloMessage = (props) => <div>Hello {props.name}</div>;
ReactDOM.render(<HelloMessage name="Sebastian" />, mountNode);
```
This simplified component API is intended for components that are pure functions of their props. These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate.
However, you may still specify `.propTypes` and `.defaultProps` by setting them as properties on the function, just as you would set them on an ES6 class:
```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:
>
> Because stateless functions don't have a backing instance, you can't attach a ref to a stateless function component. Normally this isn't an issue, since stateless functions do not provide an imperative API. Without an imperative API, there isn't much you could do with an instance anyway. However, if a user wants to find the DOM node of a stateless function component, they must wrap the component in a stateful component (eg. ES6 class component) and attach the ref to the stateful wrapper component.
> NOTE:
>
> In React v0.14, stateless functional components were not permitted to return `null` or `false` (a workaround is to return a `<noscript />` instead). This was fixed in React v15, and stateless functional components are now permitted to return `null`.
In an ideal world, most of your components would be stateless functions because in the future well also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.
If a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.
+2 -2
View File
@@ -67,9 +67,9 @@ HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의
이것은 사용자 입력을 받아들이지만, 시작에서부터 140자로 값을 자릅니다.
### 체크박스와 라디오 버튼의 잠적인 문제
### 체크박스와 라디오 버튼의 잠적인 문제
변경 핸들링을 일반화하기 위해 React는 `change` 이벤트 대신에 `click` 이벤트를 사용하는 것에 주의하세요. `change` 핸들러 안에서 `preventDefault`를 호출하는 경우를 외하고 이 동작은 예상대로 동작합니다. 이런 경우 `preventDefault`를 제거하거나, `setTimeout``checked`의 전환을 넣어서 해결 가능합니다.
변경 핸들링을 일반화하기 위해 React는 `change` 이벤트 대신에 `click` 이벤트를 사용하는 것에 주의하세요. `change` 핸들러 안에서 `preventDefault`를 호출하는 경우를 외하고 이 동작은 예상대로 동작합니다. 이런 경우 `preventDefault`를 제거하거나, `setTimeout``checked`의 전환을 넣어서 해결 가능합니다.
## 제어되지 않는(Uncontrolled) 컴포넌트
+17 -11
View File
@@ -37,7 +37,7 @@ Like all DOM events, the `onChange` prop is supported on all native components a
A **controlled** `<input>` has a `value` prop. Rendering a controlled `<input>` will reflect the value of the `value` prop.
```javascript
render: function() {
render() {
return <input type="text" value="Hello!" />;
}
```
@@ -45,13 +45,18 @@ A **controlled** `<input>` has a `value` prop. Rendering a controlled `<input>`
User input will have no effect on the rendered element because React has declared the value to be `Hello!`. To update the value in response to user input, you could use the `onChange` event:
```javascript
getInitialState: function() {
return {value: 'Hello!'};
},
handleChange: function(event) {
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'Hello!'};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
},
render: function() {
}
render() {
return (
<input
type="text"
@@ -60,12 +65,13 @@ User input will have no effect on the rendered element because React has declare
/>
);
}
}
```
In this example, we are accepting the value provided by the user and updating the `value` prop of the `<input>` component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. For example:
```javascript
handleChange: function(event) {
handleChange(event) {
this.setState({value: event.target.value.substr(0, 140)});
}
```
@@ -83,7 +89,7 @@ Be aware that, in an attempt to normalize change handling for checkbox and radio
An `<input>` without a `value` property is an *uncontrolled* component:
```javascript
render: function() {
render() {
return <input type="text" />;
}
```
@@ -97,7 +103,7 @@ An **uncontrolled** component maintains its own internal state.
If you want to initialize the component with a non-empty value, you can supply a `defaultValue` prop. For example:
```javascript
render: function() {
render() {
return <input type="text" defaultValue="Hello!" />;
}
```
@@ -125,7 +131,7 @@ This renders an input *initialized* with the value, `Untitled`. When the user up
Unlike HTML, React components must represent the state of the view at any point in time and not only at initialization time. For example, in React:
```javascript
render: function() {
render() {
return <input type="text" name="title" value="Untitled" />;
}
```
+59 -60
View File
@@ -16,31 +16,36 @@ React provides a `ReactTransitionGroup` add-on component as a low-level API for
`ReactCSSTransitionGroup` is the interface to `ReactTransitions`. This is a simple element that wraps all of the components you are interested in animating. Here's an example where we fade list items in and out.
```javascript{28-30}
```javascript{33-38}
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
var TodoList = React.createClass({
getInitialState: function() {
return {items: ['hello', 'world', 'click', 'me']};
},
handleAdd: function() {
var newItems =
this.state.items.concat([prompt('Enter some text')]);
class TodoList extends React.Component {
constructor(props) {
super(props);
this.state = {items: ['hello', 'world', 'click', 'me']};
this.handleAdd = this.handleAdd.bind(this);
}
handleAdd() {
var newItems = this.state.items.concat([
prompt('Enter some text')
]);
this.setState({items: newItems});
},
handleRemove: function(i) {
}
handleRemove(i) {
var newItems = this.state.items.slice();
newItems.splice(i, 1);
this.setState({items: newItems});
},
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
{item}
</div>
);
}.bind(this));
}
render() {
var items = this.state.items.map((item, i) => (
<div key={item} onClick={() => this.handleRemove(i)}>
{item}
</div>
));
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
@@ -53,7 +58,7 @@ var TodoList = React.createClass({
</div>
);
}
});
}
```
> Note:
@@ -90,8 +95,8 @@ You'll notice that animation durations need to be specified in both the CSS and
`ReactCSSTransitionGroup` provides the optional prop `transitionAppear`, to add an extra transition phase at the initial mount of the component. There is generally no transition phase at the initial mount as the default value of `transitionAppear` is `false`. The following is an example which passes the prop `transitionAppear` with the value `true`.
```javascript{3-5}
render: function() {
```javascript{5-6}
render() {
return (
<ReactCSSTransitionGroup
transitionName="example"
@@ -153,19 +158,20 @@ It is also possible to use custom class names for each of the steps in your tran
### Animation Group Must Be Mounted To Work
In order for it to apply transitions to its children, the `ReactCSSTransitionGroup` must already be mounted in the DOM or the prop `transitionAppear` must be set to `true`. The example below would not work, because the `ReactCSSTransitionGroup` is being mounted along with the new item, instead of the new item being mounted within it. Compare this to the [Getting Started](#getting-started) section above to see the difference.
In order for it to apply transitions to its children, the `ReactCSSTransitionGroup` must already be mounted in the DOM or the prop `transitionAppear` must be set to `true`.
The example below would **not** work, because the `ReactCSSTransitionGroup` is being mounted along with the new item, instead of the new item being mounted within it. Compare this to the [Getting Started](#getting-started) section above to see the difference.
```javascript{4,6,13}
render() {
var items = this.state.items.map((item, i) => (
<div key={item} onClick={() => this.handleRemove(i)}>
<ReactCSSTransitionGroup transitionName="example">
{item}
</ReactCSSTransitionGroup>
</div>
));
```javascript{12-15}
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
<ReactCSSTransitionGroup transitionName="example">
{item}
</ReactCSSTransitionGroup>
</div>
);
}, this);
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
@@ -179,26 +185,21 @@ In order for it to apply transitions to its children, the `ReactCSSTransitionGro
In the example above, we rendered a list of items into `ReactCSSTransitionGroup`. However, the children of `ReactCSSTransitionGroup` can also be one or zero items. This makes it possible to animate a single element entering or leaving. Similarly, you can animate a new element replacing the current element. For example, we can implement a simple image carousel like this:
```javascript{10-12}
```javascript{10}
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
var ImageCarousel = React.createClass({
propTypes: {
imageSrc: React.PropTypes.string.isRequired
},
render: function() {
return (
<div>
<ReactCSSTransitionGroup
transitionName="carousel"
transitionEnterTimeout={300}
transitionLeaveTimeout={300}>
<img src={this.props.imageSrc} key={this.props.imageSrc} />
</ReactCSSTransitionGroup>
</div>
);
}
});
function ImageCarousel(props) {
return (
<div>
<ReactCSSTransitionGroup
transitionName="carousel"
transitionEnterTimeout={300}
transitionLeaveTimeout={300}>
<img src={props.imageSrc} key={props.imageSrc} />
</ReactCSSTransitionGroup>
</div>
);
}
```
### Disabling Animations
@@ -263,18 +264,16 @@ People often use `ReactTransitionGroup` to animate mounting and unmounting of a
However if you only need to render a single child inside `ReactTransitionGroup`, you can completely avoid wrapping it in a `<span>` or any other DOM component. To do this, create a custom component that renders the first child passed to it directly:
```javascript{1}
var FirstChild = React.createClass({
render: function() {
var children = React.Children.toArray(this.props.children);
return children[0] || null;
}
});
```javascript
function FirstChild(props) {
var childrenArray = React.Children.toArray(props.children);
return childrenArray[0] || null;
}
```
Now you can specify `FirstChild` as the `component` prop in `<ReactTransitionGroup>` props and avoid any wrappers in the result DOM:
```javascript{1}
```javascript
<ReactTransitionGroup component={FirstChild}>
{someCondition ? <MyComponent /> : null}
</ReactTransitionGroup>
+2 -2
View File
@@ -6,7 +6,7 @@ prev: two-way-binding-helpers.html
next: clone-with-props.html
---
`ReactTestUtils` makes it easy to test React components in the testing framework of your choice (we use [Jest](https://facebook.github.io/jest/)).
`ReactTestUtils` makes it easy to test React components in the testing framework of your choice. At Facebook we use [Jest](https://facebook.github.io/jest/) for painless JavaScript testing. Learn how to get started with Jest through the Jest website's [React Tutorial](http://facebook.github.io/jest/docs/tutorial-react.html#content).
```
var ReactTestUtils = require('react-addons-test-utils');
@@ -14,7 +14,7 @@ var ReactTestUtils = require('react-addons-test-utils');
> Note:
>
> Airbnb has released a testing utility called Enzyme, which makes it easy to assert, manipulate, and traverse your React Components' output. If you're deciding on a unit testing library, it's worth checking out: [http://airbnb.io/enzyme/](http://airbnb.io/enzyme/)
> Airbnb has released a testing utility called Enzyme, which makes it easy to assert, manipulate, and traverse your React Components' output. If you're deciding on a unit testing utility to use together with Jest, or any other test runner, it's worth checking out: [http://airbnb.io/enzyme/](http://airbnb.io/enzyme/)
### Simulate
+22 -42
View File
@@ -11,24 +11,15 @@ In most cases, you can use the `key` prop to specify keys on the elements you're
That is, if you have a component such as:
```js
var Swapper = React.createClass({
propTypes: {
// `leftChildren` and `rightChildren` can be a string, element, array, etc.
leftChildren: React.PropTypes.node,
rightChildren: React.PropTypes.node,
swapped: React.PropTypes.bool
},
render: function() {
var children;
if (this.props.swapped) {
children = [this.props.rightChildren, this.props.leftChildren];
} else {
children = [this.props.leftChildren, this.props.rightChildren];
}
return <div>{children}</div>;
function Swapper(props) {
var children;
if (props.swapped) {
children = [props.rightChildren, props.leftChildren];
} else {
children = [props.leftChildren, props.rightChildren];
}
});
return <div>{children}</div>;
}
```
The children will unmount and remount as you change the `swapped` prop because there aren't any keys marked on the two sets of children.
@@ -42,34 +33,23 @@ Instead of creating arrays, we write:
```js
var createFragment = require('react-addons-create-fragment');
if (this.props.swapped) {
children = createFragment({
right: this.props.rightChildren,
left: this.props.leftChildren
});
} else {
children = createFragment({
left: this.props.leftChildren,
right: this.props.rightChildren
});
function Swapper(props) {
var children;
if (props.swapped) {
children = createFragment({
right: props.rightChildren,
left: props.leftChildren
});
} else {
children = createFragment({
left: props.leftChildren,
right: props.rightChildren
});
}
return <div>{children}</div>;
}
```
The keys of the passed object (that is, `left` and `right`) are used as keys for the entire set of children, and the order of the object's keys is used to determine the order of the rendered children. With this change, the two sets of children will be properly reordered in the DOM without unmounting.
The return value of `createFragment` should be treated as an opaque object; you can use the `React.Children` helpers to loop through a fragment but should not access it directly. Note also that we're relying on the JavaScript engine preserving object enumeration order here, which is not guaranteed by the spec but is implemented by all major browsers and VMs for objects with non-numeric keys.
> **Note:**
>
> In the future, `createFragment` may be replaced by an API such as
>
> ```js
> return (
> <div>
> <x:frag key="right">{this.props.rightChildren}</x:frag>,
> <x:frag key="left">{this.props.leftChildren}</x:frag>
> </div>
> );
> ```
>
> allowing you to assign keys directly in JSX without adding wrapper elements.
+1 -1
View File
@@ -41,7 +41,7 @@ June 2 & 3 in Paris, France
### ReactRally 2016
August 25-26 in Salt Lake City, UT
[Website](http://www.reactrally.com/) - [Schedule](http://www.reactrally.com/#/schedule)
[Website](http://www.reactrally.com/) - [Schedule](http://www.reactrally.com/#/schedule) - [Videos](https://www.youtube.com/playlist?list=PLUD4kD-wL_zYSfU3tIYsb4WqfFQzO_EjQ)
### ReactNext 2016
September 15 in Tel Aviv, Israel
+1 -1
View File
@@ -161,7 +161,7 @@ ReactDOM.render(
## 下一步
去看看[入门教程](/react/docs/tutorial.html) 和入门教程包 `examples` 目录下的其它例子学习更多。
去看看[入门教程](/react/docs/tutorial-zh-CN.html) 和入门教程包 `examples` 目录下的其它例子学习更多。
我们还有一个社区开发者共建的 Wiki:[workflows, UI-components, routing, data management etc.](https://github.com/facebook/react/wiki/Complementary-Tools)
@@ -37,6 +37,10 @@ object getInitialState()
Invocato una volta prima che il componente venga montato. Il valore di ritorno sarà usato come il valore iniziale di `this.state`.
> Nota:
>
> Questo metodo non è disponibile il componenti `class` ES6 che estendono `React.Component`. Per maggiori informazioni, leggi la nostra documentazione sulle [classi ES6](/react/docs/reusable-components.html#es6-classes).
### getDefaultProps
@@ -37,6 +37,10 @@ object getInitialState()
컴포넌트가 마운트되기 전에 한번 호출됩니다. 리턴값은 `this.state`의 초기값으로 사용됩니다.
> 주의:
>
> 이 메소드는 `React.Component`를 확장한 ES6 `class` 컴포넌트에서는 사용할 수 없습니다. 관한 더 자세한 정보는 [ES6 클래스](/react/docs/reusable-components-ko-KR.html#es6-클래스)를 읽어보세요.
### getDefaultProps
+4
View File
@@ -37,6 +37,10 @@ object getInitialState()
Invoked once before the component is mounted. The return value will be used as the initial value of `this.state`.
> Note:
>
> This method is not available on ES6 `class` components that extend `React.Component`. For more information, please read our documentation about [ES6 classes](/react/docs/reusable-components.html#es6-classes).
### getDefaultProps
+11 -7
View File
@@ -11,7 +11,7 @@ next: tags-and-attributes-zh-CN.html
当调用 `React.createClass()` 创建一个组件类时,你应该提供一个包含有 `render` 方法以及可选的其他生命周期方法的 规范(Specifications)对象.
> 注意:
>
>
> 同样可以使用单纯的 JavaScript 类作为组件类. 这些类可以实现大多数相同的方法,虽然有一些不同.更多关于不同的信息,请阅读我们关于[ES6 classes](/react/docs/reusable-components.html#es6-classes)的文档.
### render
@@ -21,22 +21,26 @@ ReactElement render()
```
`render()` 是必须的
当被调用时,它应该检查 `this.props``this.state` 并返回单个子元素.这个子元素即可以是一个 对原生DOM的虚拟表达(比如 `<div />``React.DOM.div()`)也可以是其他你自定义的复合组件.
你也可以返回 `null``false` 来指示你不想要任何东西被渲染.幕后,React 渲染一个 `<noscript>` tag 来与我们当前的diffing算法协同工作.当返回 `null``false` ,`ReactDOM.findDOMNode(this)` 会返回 `null`.
`render()` 函数应该是纯净的,意味着它不改变组件的状态,它在每次调用时返回相同的结果,并且它不读和写 DOM 或者其他方式与浏览器互动(例如,使用 `setTimeout`).如果你需要与浏览器互动,在 `componentDidMount()` 里执行你的工作,或者其他生命周期方法里.保持 `render()` 纯净使服务器渲染更实用并且让组件更容易被思考.
### getInitialState
```javascript
object getInitialState()
```
当组件被挂载时调用一次.返回值会被用作为 `this.state` 的初始值.
> 注意:
>
> 这个方法在从 `React.Component` 扩展的 ES6 `class` 组件里不可用。 更多的信息,请阅读我们关于[ES6 classes](/react/docs/reusable-components.html#es6-classes)的文档.
### getDefaultProps
+2 -2
View File
@@ -45,7 +45,7 @@ Per questo tutorial renderemo il tutto il più semplice possibile. Incluso nel p
<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>
<script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
</head>
<body>
<div id="content"></div>
@@ -232,7 +232,7 @@ Per prima cosa, aggiungiamo la libreria di terze parti **marked** alla tua appli
<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>
<script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
</head>
```
+2 -2
View File
@@ -45,7 +45,7 @@ next: thinking-in-react-ja-JP.html
<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>
<script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
</head>
<body>
@@ -229,7 +229,7 @@ Markdown はインラインでテキストをフォーマットする簡単な
<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>
<script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
</head>
```
+2 -2
View File
@@ -45,7 +45,7 @@ next: thinking-in-react-ko-KR.html
<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>
<script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
</head>
<body>
<div id="content"></div>
@@ -235,7 +235,7 @@ Markdown은 텍스트를 포맷팅하는 간단한 방식입니다. 예를 들
<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>
<script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
</head>
```
+2 -2
View File
@@ -43,9 +43,9 @@ For this tutorial, we're going to make it as easy as possible. Included in the s
<title>React Tutorial</title>
<script src="https://unpkg.com/react@{{site.react_version}}/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@{{site.react_version}}/dist/react-dom.js"></script>
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.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>
<script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
</head>
<body>
<div id="content"></div>
+2 -2
View File
@@ -45,7 +45,7 @@ next: thinking-in-react-zh-CN.html
<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>
<script src="https://unpkg.com/remarkable@1.7.1/dist/remarkable.min.js"></script>
</head>
<body>
<div id="content"></div>
@@ -783,4 +783,4 @@ var CommentBox = React.createClass({
### 祝贺!
你刚刚通过几个简单的步骤建立了一个评论框。学习更多关于[为什么使用 React](/react/docs/why-react-zh-CN.html), 或者深入 [API 参考](/react/docs/top-level-api.html) 开始钻研!祝你好运!
你刚刚通过几个简单的步骤建立了一个评论框。学习更多关于[为什么使用 React](/react/docs/why-react-zh-CN.html), 或者深入 [API 参考](/react/docs/top-level-api-zh-CN.html) 开始钻研!祝你好运!
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 KiB

+1 -1
View File
@@ -1,5 +1,5 @@
/**
* ReactDOM v15.3.1
* ReactDOM v15.3.2
*
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
+172 -177
View File
@@ -1,5 +1,5 @@
/**
* React v15.3.1
* React v15.3.2
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
/**
@@ -316,8 +316,10 @@ function getNativeBeforeInputChars(topLevelType, nativeEvent) {
function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
// If we are currently composing (IME) and using a fallback to do so,
// try to extract the composed characters from the fallback object.
// If composition event is available, we extract a string only at
// compositionevent, otherwise extract it at fallback events.
if (currentComposition) {
if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) {
if (topLevelType === topLevelTypes.topCompositionEnd || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) {
var chars = currentComposition.getData();
FallbackCompositionState.release(currentComposition);
currentComposition = null;
@@ -935,7 +937,7 @@ function shouldUseChangeEvent(elem) {
var doesChangeEventBubble = false;
if (ExecutionEnvironment.canUseDOM) {
// See `handleChange` comment below
doesChangeEventBubble = isEventSupported('change') && (!('documentMode' in document) || document.documentMode > 8);
doesChangeEventBubble = isEventSupported('change') && (!document.documentMode || document.documentMode > 8);
}
function manualDispatchChangeEvent(nativeEvent) {
@@ -1001,7 +1003,7 @@ if (ExecutionEnvironment.canUseDOM) {
// deleting text, so we ignore its input events.
// IE10+ fire input events to often, such when a placeholder
// changes or when an input with a placeholder is focused.
isInputEventSupported = isEventSupported('input') && (!('documentMode' in document) || document.documentMode > 11);
isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 11);
}
/**
@@ -3298,6 +3300,8 @@ var HTMLDOMPropertyConfig = {
allowFullScreen: HAS_BOOLEAN_VALUE,
allowTransparency: 0,
alt: 0,
// specifies target context for links with `preload` type
as: 0,
async: HAS_BOOLEAN_VALUE,
autoComplete: 0,
// autoFocus is polyfilled/normalized by AutoFocusUtils
@@ -3378,6 +3382,7 @@ var HTMLDOMPropertyConfig = {
optimum: 0,
pattern: 0,
placeholder: 0,
playsInline: HAS_BOOLEAN_VALUE,
poster: 0,
preload: 0,
profile: 0,
@@ -4175,6 +4180,19 @@ var ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, {
return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle);
},
/**
* Protect against document.createEvent() returning null
* Some popup blocker extensions appear to do this:
* https://github.com/facebook/react/issues/6887
*/
supportsEventPageXY: function () {
if (!document.createEvent) {
return false;
}
var ev = document.createEvent('MouseEvent');
return ev != null && 'pageX' in ev;
},
/**
* Listens to window scroll and resize events. We cache scroll values so that
* application code can access them without triggering reflows.
@@ -4188,7 +4206,7 @@ var ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, {
*/
ensureScrollValueMonitoring: function () {
if (hasEventPageXY === undefined) {
hasEventPageXY = document.createEvent && 'pageX' in document.createEvent('MouseEvent');
hasEventPageXY = ReactBrowserEventEmitter.supportsEventPageXY();
}
if (!hasEventPageXY && !isMonitoringScrollValue) {
var refresh = ViewportMetrics.refreshScrollValues;
@@ -5931,28 +5949,6 @@ function warnIfInvalidElement(Component, element) {
}
}
function invokeComponentDidMountWithTimer() {
var publicInstance = this._instance;
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidMount');
}
publicInstance.componentDidMount();
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidMount');
}
}
function invokeComponentDidUpdateWithTimer(prevProps, prevState, prevContext) {
var publicInstance = this._instance;
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidUpdate');
}
publicInstance.componentDidUpdate(prevProps, prevState, prevContext);
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidUpdate');
}
}
function shouldConstruct(Component) {
return !!(Component.prototype && Component.prototype.isReactComponent);
}
@@ -5961,6 +5957,23 @@ function isPureComponent(Component) {
return !!(Component.prototype && Component.prototype.isPureReactComponent);
}
// Separated into a function to contain deoptimizations caused by try/finally.
function measureLifeCyclePerf(fn, debugID, timerType) {
if (debugID === 0) {
// Top-level wrappers (see ReactMount) and empty components (see
// ReactDOMEmptyComponent) are invisible to hooks and devtools.
// Both are implementation details that should go away in the future.
return fn();
}
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(debugID, timerType);
try {
return fn();
} finally {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(debugID, timerType);
}
}
/**
* ------------------ The Life-Cycle of a Composite Component ------------------
*
@@ -6052,6 +6065,8 @@ var ReactCompositeComponentMixin = {
* @internal
*/
mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
var _this = this;
this._context = context;
this._mountOrder = nextMountID++;
this._hostParent = hostParent;
@@ -6141,7 +6156,11 @@ var ReactCompositeComponentMixin = {
if (inst.componentDidMount) {
if ("development" !== 'production') {
transaction.getReactMountReady().enqueue(invokeComponentDidMountWithTimer, this);
transaction.getReactMountReady().enqueue(function () {
measureLifeCyclePerf(function () {
return inst.componentDidMount();
}, _this._debugID, 'componentDidMount');
});
} else {
transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
}
@@ -6165,35 +6184,26 @@ var ReactCompositeComponentMixin = {
_constructComponentWithoutOwner: function (doConstruct, publicProps, publicContext, updateQueue) {
var Component = this._currentElement.type;
var instanceOrElement;
if (doConstruct) {
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'ctor');
}
}
instanceOrElement = new Component(publicProps, publicContext, updateQueue);
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'ctor');
}
}
} else {
// This can still be an instance in case of factory components
// but we'll count this as time spent rendering as the more common case.
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');
}
}
instanceOrElement = Component(publicProps, publicContext, updateQueue);
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');
}
return measureLifeCyclePerf(function () {
return new Component(publicProps, publicContext, updateQueue);
}, this._debugID, 'ctor');
} else {
return new Component(publicProps, publicContext, updateQueue);
}
}
return instanceOrElement;
// This can still be an instance in case of factory components
// but we'll count this as time spent rendering as the more common case.
if ("development" !== 'production') {
return measureLifeCyclePerf(function () {
return Component(publicProps, publicContext, updateQueue);
}, this._debugID, 'render');
} else {
return Component(publicProps, publicContext, updateQueue);
}
},
performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
@@ -6202,11 +6212,6 @@ var ReactCompositeComponentMixin = {
try {
markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
} catch (e) {
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onError();
}
}
// Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint
transaction.rollback(checkpoint);
this._instance.unstable_handleError(e);
@@ -6227,17 +6232,19 @@ var ReactCompositeComponentMixin = {
performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
var inst = this._instance;
var debugID = 0;
if ("development" !== 'production') {
debugID = this._debugID;
}
if (inst.componentWillMount) {
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillMount');
}
}
inst.componentWillMount();
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillMount');
}
measureLifeCyclePerf(function () {
return inst.componentWillMount();
}, debugID, 'componentWillMount');
} else {
inst.componentWillMount();
}
// When mounting, calls to `setState` by `componentWillMount` will set
// `this._pendingStateQueue` without triggering a re-render.
@@ -6257,15 +6264,12 @@ var ReactCompositeComponentMixin = {
);
this._renderedComponent = child;
var selfDebugID = 0;
if ("development" !== 'production') {
selfDebugID = this._debugID;
}
var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context), selfDebugID);
var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context), debugID);
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);
if (debugID !== 0) {
var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
}
}
@@ -6286,24 +6290,22 @@ var ReactCompositeComponentMixin = {
if (!this._renderedComponent) {
return;
}
var inst = this._instance;
if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {
inst._calledComponentWillUnmount = true;
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUnmount');
}
}
if (safely) {
var name = this.getName() + '.componentWillUnmount()';
ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));
} else {
inst.componentWillUnmount();
}
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUnmount');
if ("development" !== 'production') {
measureLifeCyclePerf(function () {
return inst.componentWillUnmount();
}, this._debugID, 'componentWillUnmount');
} else {
inst.componentWillUnmount();
}
}
}
@@ -6390,13 +6392,21 @@ var ReactCompositeComponentMixin = {
_processChildContext: function (currentContext) {
var Component = this._currentElement.type;
var inst = this._instance;
if ("development" !== 'production') {
ReactInstrumentation.debugTool.onBeginProcessingChildContext();
}
var childContext = inst.getChildContext && inst.getChildContext();
if ("development" !== 'production') {
ReactInstrumentation.debugTool.onEndProcessingChildContext();
var childContext;
if (inst.getChildContext) {
if ("development" !== 'production') {
ReactInstrumentation.debugTool.onBeginProcessingChildContext();
try {
childContext = inst.getChildContext();
} finally {
ReactInstrumentation.debugTool.onEndProcessingChildContext();
}
} else {
childContext = inst.getChildContext();
}
}
if (childContext) {
!(typeof Component.childContextTypes === 'object') ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', this.getName() || 'ReactCompositeComponent') : _prodInvariant('107', this.getName() || 'ReactCompositeComponent') : void 0;
if ("development" !== 'production') {
@@ -6491,15 +6501,11 @@ var ReactCompositeComponentMixin = {
// immediately reconciled instead of waiting for the next batch.
if (willReceive && inst.componentWillReceiveProps) {
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillReceiveProps');
}
}
inst.componentWillReceiveProps(nextProps, nextContext);
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillReceiveProps');
}
measureLifeCyclePerf(function () {
return inst.componentWillReceiveProps(nextProps, nextContext);
}, this._debugID, 'componentWillReceiveProps');
} else {
inst.componentWillReceiveProps(nextProps, nextContext);
}
}
@@ -6509,15 +6515,11 @@ var ReactCompositeComponentMixin = {
if (!this._pendingForceUpdate) {
if (inst.shouldComponentUpdate) {
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'shouldComponentUpdate');
}
}
shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'shouldComponentUpdate');
}
shouldUpdate = measureLifeCyclePerf(function () {
return inst.shouldComponentUpdate(nextProps, nextState, nextContext);
}, this._debugID, 'shouldComponentUpdate');
} else {
shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
}
} else {
if (this._compositeType === CompositeTypes.PureClass) {
@@ -6583,6 +6585,8 @@ var ReactCompositeComponentMixin = {
* @private
*/
_performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {
var _this2 = this;
var inst = this._instance;
var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);
@@ -6597,15 +6601,11 @@ var ReactCompositeComponentMixin = {
if (inst.componentWillUpdate) {
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUpdate');
}
}
inst.componentWillUpdate(nextProps, nextState, nextContext);
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUpdate');
}
measureLifeCyclePerf(function () {
return inst.componentWillUpdate(nextProps, nextState, nextContext);
}, this._debugID, 'componentWillUpdate');
} else {
inst.componentWillUpdate(nextProps, nextState, nextContext);
}
}
@@ -6619,7 +6619,9 @@ var ReactCompositeComponentMixin = {
if (hasComponentDidUpdate) {
if ("development" !== 'production') {
transaction.getReactMountReady().enqueue(invokeComponentDidUpdateWithTimer.bind(this, prevProps, prevState, prevContext), this);
transaction.getReactMountReady().enqueue(function () {
measureLifeCyclePerf(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), _this2._debugID, 'componentDidUpdate');
});
} else {
transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
}
@@ -6636,6 +6638,12 @@ var ReactCompositeComponentMixin = {
var prevComponentInstance = this._renderedComponent;
var prevRenderedElement = prevComponentInstance._currentElement;
var nextRenderedElement = this._renderValidatedComponent();
var debugID = 0;
if ("development" !== 'production') {
debugID = this._debugID;
}
if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));
} else {
@@ -6648,15 +6656,12 @@ var ReactCompositeComponentMixin = {
);
this._renderedComponent = child;
var selfDebugID = 0;
if ("development" !== 'production') {
selfDebugID = this._debugID;
}
var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context), selfDebugID);
var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context), debugID);
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);
if (debugID !== 0) {
var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
}
}
@@ -6678,17 +6683,14 @@ var ReactCompositeComponentMixin = {
*/
_renderValidatedComponentWithoutOwnerOrContext: function () {
var inst = this._instance;
var renderedComponent;
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');
}
}
var renderedComponent = inst.render();
if ("development" !== 'production') {
if (this._debugID !== 0) {
ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');
}
renderedComponent = measureLifeCyclePerf(function () {
return inst.render();
}, this._debugID, 'render');
} else {
renderedComponent = inst.render();
}
if ("development" !== 'production') {
@@ -6739,7 +6741,7 @@ var ReactCompositeComponentMixin = {
var publicComponentInstance = component.getPublicInstance();
if ("development" !== 'production') {
var componentName = component && component.getName ? component.getName() : 'a component';
"development" !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0;
"development" !== 'production' ? warning(publicComponentInstance != null || component._compositeType !== CompositeTypes.StatelessFunctional, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0;
}
var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;
refs[ref] = publicComponentInstance;
@@ -7163,9 +7165,9 @@ function optionPostMount() {
ReactDOMOption.postMountWrapper(inst);
}
var setContentChildForInstrumentation = emptyFunction;
var setAndValidateContentChildDev = emptyFunction;
if ("development" !== 'production') {
setContentChildForInstrumentation = function (content) {
setAndValidateContentChildDev = function (content) {
var hasExistingContent = this._contentDebugID != null;
var debugID = this._debugID;
// This ID represents the inlined child that has no backing instance:
@@ -7179,6 +7181,7 @@ if ("development" !== 'production') {
return;
}
validateDOMNesting(null, String(content), this, this._ancestorInfo);
this._contentDebugID = contentDebugID;
if (hasExistingContent) {
ReactInstrumentation.debugTool.onBeforeUpdateComponent(contentDebugID, content);
@@ -7353,7 +7356,7 @@ function ReactDOMComponent(element) {
this._flags = 0;
if ("development" !== 'production') {
this._ancestorInfo = null;
setContentChildForInstrumentation.call(this, null);
setAndValidateContentChildDev.call(this, null);
}
}
@@ -7453,7 +7456,7 @@ ReactDOMComponent.Mixin = {
if (parentInfo) {
// parentInfo should always be present except for the top-level
// component when server rendering
validateDOMNesting(this._tag, this, parentInfo);
validateDOMNesting(this._tag, null, this, parentInfo);
}
this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(parentInfo, this._tag, this);
}
@@ -7622,7 +7625,7 @@ ReactDOMComponent.Mixin = {
// TODO: Validate that text is allowed as a child of this node
ret = escapeTextContentForBrowser(contentToUse);
if ("development" !== 'production') {
setContentChildForInstrumentation.call(this, contentToUse);
setAndValidateContentChildDev.call(this, contentToUse);
}
} else if (childrenToUse != null) {
var mountImages = this.mountChildren(childrenToUse, transaction, context);
@@ -7659,7 +7662,7 @@ ReactDOMComponent.Mixin = {
if (contentToUse != null) {
// TODO: Validate that text is allowed as a child of this node
if ("development" !== 'production') {
setContentChildForInstrumentation.call(this, contentToUse);
setAndValidateContentChildDev.call(this, contentToUse);
}
DOMLazyTree.queueText(lazyTree, contentToUse);
} else if (childrenToUse != null) {
@@ -7891,7 +7894,7 @@ ReactDOMComponent.Mixin = {
if (lastContent !== nextContent) {
this.updateTextContent('' + nextContent);
if ("development" !== 'production') {
setContentChildForInstrumentation.call(this, nextContent);
setAndValidateContentChildDev.call(this, nextContent);
}
}
} else if (nextHtml != null) {
@@ -7903,7 +7906,7 @@ ReactDOMComponent.Mixin = {
}
} else if (nextChildren != null) {
if ("development" !== 'production') {
setContentChildForInstrumentation.call(this, null);
setAndValidateContentChildDev.call(this, null);
}
this.updateChildren(nextChildren, transaction, context);
@@ -7958,7 +7961,7 @@ ReactDOMComponent.Mixin = {
this._wrapperState = null;
if ("development" !== 'production') {
setContentChildForInstrumentation.call(this, null);
setAndValidateContentChildDev.call(this, null);
}
},
@@ -8541,7 +8544,7 @@ function forceUpdateIfMounted() {
function isControlled(props) {
var usesChecked = props.type === 'checkbox' || props.type === 'radio';
return usesChecked ? props.checked !== undefined : props.value !== undefined;
return usesChecked ? props.checked != null : props.value != null;
}
/**
@@ -9455,7 +9458,7 @@ _assign(ReactDOMTextComponent.prototype, {
if (parentInfo) {
// parentInfo should always be present except for the top-level
// component when server rendering
validateDOMNesting('#text', this, parentInfo);
validateDOMNesting(null, this._stringText, this, parentInfo);
}
}
@@ -10191,12 +10194,6 @@ var ReactDebugTool = {
endLifeCycleTimer(debugID, timerType);
emitEvent('onEndLifeCycleTimer', debugID, timerType);
},
onError: function (debugID) {
if (currentTimerDebugID != null) {
endLifeCycleTimer(currentTimerDebugID, currentTimerType);
}
emitEvent('onError', debugID);
},
onBeginProcessingChildContext: function () {
emitEvent('onBeginProcessingChildContext');
},
@@ -10605,14 +10602,6 @@ ReactElement.createElement = function (type, config, children) {
var source = null;
if (config != null) {
if ("development" !== 'production') {
"development" !== 'production' ? warning(
/* eslint-disable no-proto */
config.__proto__ == null || config.__proto__ === Object.prototype,
/* eslint-enable no-proto */
'React.createElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;
}
if (hasValidRef(config)) {
ref = config.ref;
}
@@ -10713,14 +10702,6 @@ ReactElement.cloneElement = function (element, config, children) {
var owner = element._owner;
if (config != null) {
if ("development" !== 'production') {
"development" !== 'production' ? warning(
/* eslint-disable no-proto */
config.__proto__ == null || config.__proto__ === Object.prototype,
/* eslint-enable no-proto */
'React.cloneElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;
}
if (hasValidRef(config)) {
// Silently steal the ref from the parent.
ref = config.ref;
@@ -14854,7 +14835,7 @@ module.exports = ReactUpdates;
'use strict';
module.exports = '15.3.1';
module.exports = '15.3.2';
},{}],98:[function(_dereq_,module,exports){
/**
* Copyright 2013-present, Facebook, Inc.
@@ -15194,7 +15175,7 @@ var eventTypes = {
bubbled: keyOf({ onSelect: null }),
captured: keyOf({ onSelectCapture: null })
},
dependencies: [topLevelTypes.topBlur, topLevelTypes.topContextMenu, topLevelTypes.topFocus, topLevelTypes.topKeyDown, topLevelTypes.topMouseDown, topLevelTypes.topMouseUp, topLevelTypes.topSelectionChange]
dependencies: [topLevelTypes.topBlur, topLevelTypes.topContextMenu, topLevelTypes.topFocus, topLevelTypes.topKeyDown, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown, topLevelTypes.topMouseUp, topLevelTypes.topSelectionChange]
}
};
@@ -16260,7 +16241,8 @@ _assign(SyntheticEvent.prototype, {
if (event.preventDefault) {
event.preventDefault();
} else {
} else if (typeof event.returnValue !== 'unknown') {
// eslint-disable-line valid-typeof
event.returnValue = false;
}
this.isDefaultPrevented = emptyFunction.thatReturnsTrue;
@@ -18650,9 +18632,9 @@ var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {
reusableSVGContainer = reusableSVGContainer || document.createElement('div');
reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
var newNodes = reusableSVGContainer.firstChild.childNodes;
for (var i = 0; i < newNodes.length; i++) {
node.appendChild(newNodes[i]);
var svgNode = reusableSVGContainer.firstChild;
while (svgNode.firstChild) {
node.appendChild(svgNode.firstChild);
}
} else {
node.innerHTML = html;
@@ -19259,11 +19241,16 @@ if ("development" !== 'production') {
var didWarn = {};
validateDOMNesting = function (childTag, childInstance, ancestorInfo) {
validateDOMNesting = function (childTag, childText, childInstance, ancestorInfo) {
ancestorInfo = ancestorInfo || emptyAncestorInfo;
var parentInfo = ancestorInfo.current;
var parentTag = parentInfo && parentInfo.tag;
if (childText != null) {
"development" !== 'production' ? warning(childTag == null, 'validateDOMNesting: when childText is passed, childTag should be null') : void 0;
childTag = '#text';
}
var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
var problematic = invalidParent || invalidAncestor;
@@ -19311,7 +19298,15 @@ if ("development" !== 'production') {
didWarn[warnKey] = true;
var tagDisplayName = childTag;
if (childTag !== '#text') {
var whitespaceInfo = '';
if (childTag === '#text') {
if (/\S/.test(childText)) {
tagDisplayName = 'Text nodes';
} else {
tagDisplayName = 'Whitespace text nodes';
whitespaceInfo = ' Make sure you don\'t have any extra whitespace between tags on ' + 'each line of your source code.';
}
} else {
tagDisplayName = '<' + childTag + '>';
}
@@ -19320,7 +19315,7 @@ if ("development" !== 'production') {
if (ancestorTag === 'table' && childTag === 'tr') {
info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
}
"development" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>. ' + 'See %s.%s', tagDisplayName, ancestorTag, ownerInfo, info) : void 0;
"development" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>.%s ' + 'See %s.%s', tagDisplayName, ancestorTag, whitespaceInfo, ownerInfo, info) : void 0;
} else {
"development" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0;
}
+4 -4
View File
File diff suppressed because one or more lines are too long
+13
View File
@@ -0,0 +1,13 @@
---
id: introduction-ru-RU
title: Введение
layout: tips
permalink: tips/introduction-ru-RU.html
next: inline-styles-ru-RU.html
---
Данный раздел советов по React содержит краткую информацию, которая поможет ответить на многие вопросы и предостеречь от распространенных ошибок.
## Принятие участия
Чтобы принять участие необходимо отправить pull request в [репозиторий React](https://github.com/facebook/react) следуя [данной инструкции](https://github.com/facebook/react/tree/master/docs). Если есть решение, которое нуждается в обсуждении перед тем как сделать PR, можно обратиться за помощью на [#reactjs канал на freenode](irc://chat.freenode.net/reactjs) или [discuss.reactjs.org форум](https://discuss.reactjs.org/).
+23
View File
@@ -0,0 +1,23 @@
---
id: inline-styles-ru-RU
title: Встроенные стили
layout: tips
permalink: tips/inline-styles-ru-RU.html
next: if-else-in-JSX-ru-RU.html
prev: introduction-ru-RU.html
---
В React, встроенные стили не указываются в виде строки. Вместо этого они определяются как объект, ключ которого является camelCase версией названия стиля, а значение которого является значением стиля, обычно строкой ([подробнее об этом далее](/react/tips/style-props-value-px.html)):
```js
var divStyle = {
color: 'white',
backgroundImage: 'url(' + imgUrl + ')',
WebkitTransition: 'all', // обратите внимание на заглавную 'W'
msTransition: 'all' // 'ms' это единственный префикс в нижнем регистре
};
ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode);
```
Ключи стиля указываются в camelCase, в прямом соответствии с названиями свойств DOM-узлов в JS (например, `node.style.backgroundImage`). Префиксы [отличные от `ms`](http://www.andismith.com/blog/2012/02/modernizr-prefixed/) должны начинаться с заглавной буквы. Вот почему у `WebkitTransition` в верхнем регистре "W".
+81
View File
@@ -0,0 +1,81 @@
---
id: if-else-in-JSX-ru-RU
title: If-Else в JSX
layout: tips
permalink: tips/if-else-in-JSX-ru-RU.html
prev: inline-styles-ru-RU.html
next: self-closing-tag-ru-RU.html
---
Некоторые конструкции, такие как `if-else`, нельзя использовать внутри JSX, так как JSX в результате преобразуется в вызов функции JS, как показано в примере:
```js
// JSX:
ReactDOM.render(<div id="msg">Hello World!</div>, mountNode);
// Преобразованный в JS:
ReactDOM.render(React.createElement("div", {id:"msg"}, "Hello World!"), mountNode);
```
Это означает что оператор `if` нельзя встроить таким образом:
```js
// JSX:
<div id={if (condition) { 'msg' }}>Hello World!</div>
// Преобразованный в JS:
React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");
```
В результате преобразования получается неверный JS код. В таких случаях используется тернарный условный оператор:
```js
ReactDOM.render(<div id={condition ? 'msg' : null}>Hello World!</div>, mountNode);
```
Если тернарного оператора недостаточно, вы можете вынести оператор `if`, определяющий выбор компонентов, вне JSX:
```js
var loginButton;
if (loggedIn) {
loginButton = <LogoutButton />;
} else {
loginButton = <LoginButton />;
}
return (
<nav>
<Home />
{loginButton}
</nav>
);
```
Также вы можете обернуть код в [немедленно вызываемую функцию](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression) и расположить её _внутри_ JSX.
```js
return (
<section>
<h1>Color</h1>
<h3>Name</h3>
<p>{this.state.color || "white"}</p>
<h3>Hex</h3>
<p>
{(() => {
switch (this.state.color) {
case "red": return "#FF0000";
case "green": return "#00FF00";
case "blue": return "#0000FF";
default: return "#FFFFFF";
}
})()}
</p>
</section>
);
```
> Примечание:
>
> В приведенном выше примере, используется [функция-стрелка](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) из ES6 для связи со значением `this`.
Вы можете попробовать этот синтаксис внутри [Babel REPL](https://babeljs.io/repl/).
+14
View File
@@ -0,0 +1,14 @@
---
id: self-closing-tag-ru-RU
title: Одиночный тег
layout: tips
permalink: tips/self-closing-tag-ru-RU.html
prev: if-else-in-JSX-ru-RU.html
next: maximum-number-of-jsx-root-nodes-ru-RU.html
---
В JSX все теги необходимо закрывать. Это можно сделать либо в открывающем теге `<MyComponent />`, либо отдельным закрывающим тегом `</MyComponent>`.
> Примечание:
>
> Любой React компонент может быть одиночным: `<div />` это то же самое, что `<div></div>`.
@@ -0,0 +1,12 @@
---
id: maximum-number-of-jsx-root-nodes-ru-RU
title: Максимальное количество корневых JSX-узлов
layout: tips
permalink: tips/maximum-number-of-jsx-root-nodes-ru-RU.html
prev: self-closing-tag-ru-RU.html
next: style-props-value-px-ru-RU.html
---
Из метода `render` компонента пока что можно вернуть только один узел. Если нужно вернуть, например, несколько `div`, оберните их в `div`, `span` или любой другой компонент.
Не забывайте, что JSX компилируется в обычный JS, и возвращение двух функций не имеет синтаксического смысла. Также не помещайте более одного дочернего элемента в тернарный оператор.
@@ -0,0 +1,46 @@
---
id: style-props-value-px-ru-RU
title: Краткая форма значений в пикселях для атрибута style
layout: tips
permalink: tips/style-props-value-px-ru-RU.html
prev: maximum-number-of-jsx-root-nodes-ru-RU.html
next: children-props-type.html
---
React автоматически добавляет "px" для значений, которые указаны в числовом виде и находятся внутри встроенного стиля атрибута `style`, например:
```js
var divStyle = {height: 10}; // получится "height:10px"
ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode);
```
Подробная информация о [встроенных стилях](/react/tips/inline-styles-ru-RU.html).
Иногда бывает нужно указать значение *без* единицы измерения. Для этих свойств "px" не добавляется автоматически:
- `animationIterationCount`
- `boxFlex`
- `boxFlexGroup`
- `boxOrdinalGroup`
- `columnCount`
- `fillOpacity`
- `flex`
- `flexGrow`
- `flexPositive`
- `flexShrink`
- `flexNegative`
- `flexOrder`
- `fontWeight`
- `lineClamp`
- `lineHeight`
- `opacity`
- `order`
- `orphans`
- `stopOpacity`
- `strokeDashoffset`
- `strokeOpacity`
- `strokeWidth`
- `tabSize`
- `widows`
- `zIndex`
- `zoom`
@@ -13,8 +13,8 @@ next: expose-component-functions-ko-KR.html
`GroceryList` 컴포넌트가 배열로 생성된 아이템 목록을 가지고 있다고 해봅시다. 목록의 아이템이 클릭되면 아이템의 이름이 보이길 원할 겁니다:
```js
var handleClick = function(i, props) {
console.log('클릭한 아이템: ' + props.items[i]);
var handleClick = function(i, items) {
console.log('클릭한 아이템: ' + items[i]);
}
function GroceryList(props) {
@@ -22,7 +22,7 @@ function GroceryList(props) {
<div>
{props.items.map(function(item, i) {
return (
<div onClick={handleClick.bind(this, i, props)} key={i}>{item}</div>
<div onClick={handleClick.bind(this, i, props.items)} key={i}>{item}</div>
);
})}
</div>
@@ -13,8 +13,8 @@ For child-parent communication:
Say your `GroceryList` component has a list of items generated through an array. When a list item is clicked, you want to display its name:
```js
var handleClick = function(i, props) {
console.log('You clicked: ' + props.items[i]);
var handleClick = function(i, items) {
console.log('You clicked: ' + items[i]);
}
function GroceryList(props) {
@@ -22,7 +22,7 @@ function GroceryList(props) {
<div>
{props.items.map(function(item, i) {
return (
<div onClick={handleClick.bind(this, i, props)} key={i}>{item}</div>
<div onClick={handleClick.bind(this, i, props.items)} key={i}>{item}</div>
);
})}
</div>
@@ -6,7 +6,7 @@ permalink: tips/dangerously-set-inner-html-ko-KR.html
prev: children-undefined-ko-KR.html
---
부적절히 `innerHTML`를 사용하면 [사이트 간 스크립팅 (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) 공격에 노출됩니다. 화면의 사용자 입력을 정제하다(sanitize) 오류를 내기 쉬우며, 적절하게 사용자의 입력을 정제하지 못하면 인터넷 상 [웹 취약점의 원인](https://owasptop10.googlecode.com/files/OWASP%20Top%2010%20-%202013.pdf)이 됩니다.
부적절히 `innerHTML`를 사용하면 [사이트 간 스크립팅 (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) 공격에 노출됩니다. 화면의 사용자 입력을 정제하다(sanitize) 오류를 내기 쉬우며, 적절하게 사용자의 입력을 정제하지 못하면 인터넷 상 [웹 취약점의 원인](https://www.owasp.org/index.php/Top_10_2013-Top_10)이 됩니다.
우리 설계철학은 안전을 "쉽게" 얻는 것입니다. 개발자는 그들의 의도를 명시적으로 알려야만 "안전하지 않는" 연산을 할 수 있습니다. `dangerouslySetInnerHTML` prop의 이름은 의도적으로 무섭게 만든 것인데, prop 값은 문자열이 아닌 객체이고 정제된 데이터를 지정하는데 쓸 수 있습니다.
+1 -1
View File
@@ -6,7 +6,7 @@ permalink: tips/dangerously-set-inner-html.html
prev: children-undefined.html
---
Improper use of the `innerHTML` can open you up to a [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) attack. Sanitizing user input for display is notoriously error-prone, and failure to properly sanitize is one of the [leading causes of web vulnerabilities](https://owasptop10.googlecode.com/files/OWASP%20Top%2010%20-%202013.pdf) on the internet.
Improper use of the `innerHTML` can open you up to a [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) attack. Sanitizing user input for display is notoriously error-prone, and failure to properly sanitize is one of the [leading causes of web vulnerabilities](https://www.owasp.org/index.php/Top_10_2013-Top_10) on the internet.
Our design philosophy is that it should be “easy” to make things safe, and developers should explicitly state their intent when performing “unsafe” operations. The prop name `dangerouslySetInnerHTML` is intentionally chosen to be frightening, and the prop value (an object instead of a string) can be used to indicate sanitized data.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "react-build",
"version": "15.3.2-rc.1",
"version": "15.3.2",
"dependencies": {
"art": {
"version": "0.10.1",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "react-build",
"private": true,
"version": "15.3.2-rc.1",
"version": "15.3.2",
"devDependencies": {
"art": "^0.10.1",
"async": "^1.5.0",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "react-addons-template",
"version": "15.3.2-rc.1",
"version": "15.3.2",
"main": "index.js",
"repository": "facebook/react",
"keywords": [
@@ -10,7 +10,7 @@
"license": "BSD-3-Clause",
"dependencies": {},
"peerDependencies": {
"react": "^15.3.2-rc.1"
"react": "^15.3.2"
},
"files": [
"LICENSE",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "react-dom",
"version": "15.3.2-rc.1",
"version": "15.3.2",
"description": "React package for working with the DOM.",
"main": "index.js",
"repository": "facebook/react",
@@ -14,7 +14,7 @@
"homepage": "https://facebook.github.io/react/",
"dependencies": {},
"peerDependencies": {
"react": "^15.3.2-rc.1"
"react": "^15.3.2"
},
"files": [
"LICENSE",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "react-native-renderer",
"version": "15.3.2-rc.1",
"version": "15.3.2",
"description": "React package for use inside react-native.",
"main": "index.js",
"repository": "facebook/react",
@@ -14,7 +14,7 @@
},
"homepage": "https://facebook.github.io/react-native/",
"dependencies": {
"react": "^15.3.2-rc.1"
"react": "^15.3.2"
},
"files": [
"LICENSE",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "react-test-renderer",
"version": "15.3.2-rc.1",
"version": "15.3.2",
"description": "React package for snapshot testing.",
"main": "index.js",
"repository": "facebook/react",
@@ -15,7 +15,7 @@
},
"homepage": "https://facebook.github.io/react/",
"peerDependencies": {
"react": "^15.3.2-rc.1"
"react": "^15.3.2"
},
"files": [
"LICENSE",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "react",
"description": "React is a JavaScript library for building user interfaces.",
"version": "15.3.2-rc.1",
"version": "15.3.2",
"keywords": [
"react"
],
+1 -1
View File
@@ -11,4 +11,4 @@
'use strict';
module.exports = '15.3.2-rc.1';
module.exports = '15.3.2';