diff options
Diffstat (limited to '')
-rw-r--r-- | devtools/docs/contributor/frontend/react.md | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/devtools/docs/contributor/frontend/react.md b/devtools/docs/contributor/frontend/react.md new file mode 100644 index 0000000000..770320f570 --- /dev/null +++ b/devtools/docs/contributor/frontend/react.md @@ -0,0 +1,157 @@ + +We use [React](http://facebook.github.io/react/) to write our user +interfaces. In here you can find an explanation of why we chose React +and a short primer on it. Additionally, we list best practices that +all devtools code should adhere to when writing React. + +# Quick Intro + +This is a very quick introduction on how to *use* React, but does not +explain in-depth the concepts behind it. If you want more in-depth +articles, I recommend the following links: + +* http://facebook.github.io/react/docs/tutorial.html - the official tutorial +* https://github.com/petehunt/react-howto - how to learn React +* http://jlongster.com/Removing-User-Interface-Complexity,-or-Why-React-is-Awesome - long read but explains the concepts in depth + +React embraces components as a way of thinking about UIs. Components +are the center of everything: they are composable like functions, +testable like JSON data, and provide lifecycle APIs for more complex +scenarios. + +A component can represent anything from a single item in a list to a +complete virtualized grid that is made up of sub-components. They can +be used to abstract out "behaviors" instead of UI elements (think of a +`Selectable` component). React's API makes it easy to break up your UI +into whatever abstractions you need. + +The core idea of a component is simple: it's something that takes +properties and returns a DOM-like structure. + +```js +function Item({ name, iconURL }) { + return div({ className: "item" }, + img({ className: "icon", href: iconURL }), + name); +} +``` + +The `div` and `span` functions refer to `React.DOM.div` and +`React.DOM.span`. React provides constructors for all DOM elements on +`React.DOM`. These conform to the standard API for creating elements: +the first argument takes properties, and the rest are children. + +You can see component composition kick in when using `Item`: + +```js +const Item = React.createFactory(require('./Item')); + +function List({ items }) { + return div({ className: "list" }, + items.map(item => Item({ name: item.name, icon: item.iconURL))); +} +``` + +You can use custom components exactly the same way you use native +ones! The only difference is we wrapped it in a factory when importing +instead of using the React.DOM functions. Factories are just a way of +turning a component into a convenient function. Without factories, you +need to do do `React.createElement(Item, { ... })`, which is exactly +the same as `Item({ ... })` if using a factory. + +## Rendering and Updating Components + +Now that we have some components, how do we render them? You use +`React.render` for that: + +```js +let items = [{ name: "Dubois", iconURL: "dubois.png" }, + { name: "Ivy", iconURL: "ivy.png" }]; + +React.render(List({ items: items }), + document.querySelector("#mount")); +``` + +This renders a `List` component, given `items`, to a DOM node with an +id of `mount`. Typically you have a top-level `App` component that is +the root of everything, and you would render it like so. + +What about updating? First, let's talk about data. The above +components take data from above and render out DOM structure. If any +user events were involved, the components would call callbacks passed +as props, so events walk back up the hierarchy. The conceptual model +is data goes down, and events come up. + +You usually want to change data in response to events, and rerender +the UI with the new data. What does that look like? There are two +places where React will rerender components: + +1\. Any additional `React.render` calls. Once a component is mounted, +you can call `React.render` again to the same place and React will see +that it's already mounted and perform an update instead of a full +render. For example, this code adds an item in response to an event +and updates the UI, and will perform optimal incremental updates: + +```js +function addItem(item) { + render([...items, item]); +} + +function render(items) { + React.render(List({ items: items, + onAddItem: addItem }), + document.querySelector("#mount")); +} + +render(items); +``` + +2\. Changing component local state. This is much more common. React +allows components to have local state, and whenever the state is +changed with the `setState` API it will rerender that specific +component. If you use component local state, you need to create a +component with `createClass`: + +```js +const App = React.createClass({ + getInitialState: function() { + return { items: [] }; + }, + + handleAddItem: function(item) { + const items = [...this.props.items, item]; + this.setState({ items: items }); + }, + + render: function() { + return List({ items: this.state.items, + onAddItem: this.handleAddItem }); + } +}); + ``` + +If you are using something like Redux to manage state this is handled +automatically for you with the library you use to bind Redux with +React. See more in [Redux](redux.md). + +## DOM Diffing + +What does it mean when React "updates" a component, and how does it +know which DOM to change? React achieves this with a technique called +DOM diffing. This alleviates the need for the programmer to worry +about how updates are actually applied to the DOM, and components can +render DOM structure declaratively in response to data. In the above +examples, when adding an item, React knows to only add a new DOM node +instead of recreating the whole list each time. + +DOM diffing is possible because our components return what's called +"virtual DOM": a lightweight JSON structure that React can use to diff +against previous versions, and generate minimal changes to the real DOM. + +This also makes it really east to test components with a real DOM: +just make sure the virtual DOM has what it should. + +## Next + +Read the [React Guidelines](react-guidelines.md) next to learn how to +write React code specifically for the devtools. |