Skip to content

Commit

Permalink
Reorg docs, write a lot of content, import a lot of stuff from dex
Browse files Browse the repository at this point in the history
  • Loading branch information
petehunt committed Jul 15, 2013
1 parent 4bbdcdb commit bb3bd76
Show file tree
Hide file tree
Showing 8 changed files with 518 additions and 21 deletions.
14 changes: 9 additions & 5 deletions docs/docs/refactor/00-table-of-contents.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Displaying data
- Components are just functions
- JSX syntax (link to separate doc?)

Handling user input
Interactivity and dynamic UIs
- Click handler example
- Event handlers / synthetic events (link to w3c docs)
- Under the hood: autoBind and event delegation (IE8 notes)
Expand All @@ -32,22 +32,25 @@ Scaling up: using multiple components
- Motivation: separate concerns
- Composition example
- Ownership (and owner vs. parent)
- Children
- Data flow (one-way data binding)
- A note on performance

Building effective reusable components
- You should build a reusable component library (CSS, testing etc)
- Prop validation
- Transferring props: a shortcut
- Mixins
- Testing

Forms
- TODO list example
- How to think about Reactive forms
- New form events and properties

Working with the browser
- The mock DOM
- Refs / getDOMNode()
- More about refs
- Component lifecycle
- Polyfills
- Browser support and polyfills

Integrating with other UI libraries
- Using jQuery plugins
Expand Down Expand Up @@ -78,3 +81,4 @@ Reference
- API
- DOM differences
- JSX gotchas
- Antipatterns
2 changes: 2 additions & 0 deletions docs/docs/refactor/02-displaying-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ setInterval(function() {

View the finished code in a web browser and type your name into the text field. Notice that React is only changing the time string in the UI -- any input you put in the text field remains, even though you haven't written any code to manage this behavior. React figures it out for you and does the right thing.

The way it is able to figure this out is that React does not directly manipulate the DOM, **it uses a fast, internal mock DOM to perform diffs and computes the most efficient DOM mutation for you.**

The inputs to this component are called `props` -- short for "properties". They're passed as attributes in JSX syntax. You should think of these as immutable within the component, that is, **never write to this.props**.

## Components are just like functions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Handling User Input
# Interactivity and dynamic UIs

You've already [learned how to display data](./02-displaying-data.html) with React. Now let's look at how to make our UIs interactive.

Expand Down Expand Up @@ -34,6 +34,8 @@ React.renderComponent(

With React you simply pass your event handler as a camelCased prop similar to how you'd do it in normal HTML. React ensures that all events behave identically in IE8 and above by implementing a synthetic event system. That is, React knows how to bubble and capture events according to the spec, and the events passed to your event handler are guaranteed to be consistent with [the W3C spec](http://www.w3.org/TR/DOM-Level-3-Events/), regardless of which browser you're using.

**If you'd like to use React on a touch device** (i.e. a phone or tablet), simply call `React.initializeTouchEvents(true);` to turn them on.

## Under the hood: autoBind and event delegation

Under the hood React does a few things to keep your code performant and easy to understand.
Expand Down Expand Up @@ -62,4 +64,4 @@ A common pattern is to create several stateless components that just render data

## What should go in state?

**`this.state` should contain any data that the component's event handlers will change that should trigger a UI update.** In real apps this data tends to be very small and JSON-serializable. When building a stateful component, think about the minimal possible representation of its state, and only store those properties in `this.state`. Inside of `render()` simply compute any other information you need based on this state. You'll find that thinking about and writing applications in this way tends to lead to the most correct application, since adding redundant or computed values to state means that you need to explicitly keep them in sync rather than rely on React computing them for you.
**`this.state` should contain any data that the component's event handlers will change that should trigger a UI update.** In real apps this data tends to be very small and JSON-serializable. When building a stateful component, think about the minimal possible representation of its state, and only store those properties in `this.state`. Inside of `render()` simply compute any other information you need based on this state. You'll find that thinking about and writing applications in this way tends to lead to the most correct application, since adding redundant or computed values to state means that you need to explicitly keep them in sync rather than rely on React computing them for you.
69 changes: 55 additions & 14 deletions docs/docs/refactor/04-scaling-up.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,30 +54,71 @@ In the above example, instances of `Avatar` *own* instances of `ProfilePic` and

It's important to draw a distinciton between the owner-ownee relationship and the parent-child relationship. The owner-ownee relationship is specific to React, while the parent-child relationship is simply the one you know and love from the DOM. In the example above, `Avatar` owns the `div`, `ProfilePic` and `ProfileLink` instances, and `div` is the **parent** (but not owner) of the `ProfilePic` and `ProfileLink` instances.

## Data flow
## Children

In React, data flows from owner to owned component through `props` as discussed above. This is effectively one-way data binding: owners bind their owned component's props to some value the owner has computed based on its `props` or `state`. Since this process happens recursively, data changes are automatically reflected everywhere they are used.
When you create a React component instance, you can include additional React components or JavaScript expressions between the opening and closing tags like this:

## A note on performance
```javascript
<Parent><Child /></Parent>
```

You may be thinking that it's expensive to react to changing data if there are a large number of nodes under an owner. The good news is that JavaScript is fast and `render()` methods tend to be quite simple, so in most applications this is extremely fast. Additionally, the bottleneck is almost always the DOM mutation and not JS execution, and React will optimize this for you using batching and change detection.
`Parent` can read its children by accessing the special `this.props.children` prop.

However, sometimes you really want to have fine-grained control over your performance. In that case, simply override `shouldComponentUpdate()` to return false when you want React to skip processing of a subtree. See [the React API docs](./api.html) for more information.
### Child Reconciliation

**Note:** if `shouldComponentUpdate()` returns false when data has actually changed, React can't keep your UI in sync. Be sure you know what you're doing while using it, and only use this function when you have a noticeable performance problem. Don't underestimate how fast JavaScript is relative to the DOM.
> Reconciliation is the process by which React updates the DOM with each new render pass.
## Build reusable component libraries!
In general, children are reconciled according to the order in which they are rendered. For example, suppose two render passes generate the following respective markup:

When designing interfaces, break down the common design elements (buttons, form fields, layout components, etc) into reusable components with well-defined interfaces. That way, the next time you need to build some UI you can write much less code, which means faster development time, less bugs, and less bytes down the wire.
```html
// Render Pass 1
<Card><p>Paragraph 1</p><p>Paragraph 2</p></Card>
// Render Pass 2
<Card><p>Paragraph 2</p></Card>
```

Intuitively, `<p>Paragraph 1</p>` was removed. Instead, React will reconcile the DOM by changing the text content of the first child and destroying the last child. React reconciles according to the *order* of the children.

## Prop validation
### Stateful Children

As your app grows it's helpful to ensure that your components are used correctly. We do this using `propTypes`.
For most components, this is not a big deal. However, for stateful components that maintain data in `this.state` across render passes, this can be very problematic.

** TODO zpao **
In most cases, this can be sidestepped by hiding elements instead of destroying them:

```html
// Render Pass 1
<Card><p>Paragraph 1</p><p>Paragraph 2</p></Card>
// Render Pass 2
<Card><p style={{display: 'none'}}>Paragraph 1</p><p>Paragraph 2</p></Card>
```

## Mixins
### Dynamic Children

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](http://en.wikipedia.org/wiki/Cross-cutting_concern). React provides `mixins` to solve this problem.
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`:

This comment has been minimized.

Copy link
@albandiguer

albandiguer Jul 20, 2015

👍


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. React provides [lifecycle methods](./06-working-with-the-browser.html)
```javascript
render: function() {
var results = this.props.results;
return (
<ol>
{this.results.map(function(result) {
return <li key={result.id}>{result.text}</li>;
})}
</ol>
);
}
```

When React reconciles the keyed children, it will ensure that any child with `key` will be reordered (instead of clobbered) or destroyed (instead of reused).

## Data flow

In React, data flows from owner to owned component through `props` as discussed above. This is effectively one-way data binding: owners bind their owned component's props to some value the owner has computed based on its `props` or `state`. Since this process happens recursively, data changes are automatically reflected everywhere they are used.

## A note on performance

You may be thinking that it's expensive to react to changing data if there are a large number of nodes under an owner. The good news is that JavaScript is fast and `render()` methods tend to be quite simple, so in most applications this is extremely fast. Additionally, the bottleneck is almost always the DOM mutation and not JS execution, and React will optimize this for you using batching and change detection.

However, sometimes you really want to have fine-grained control over your performance. In that case, simply override `shouldComponentUpdate()` to return false when you want React to skip processing of a subtree. See [the React API docs](./api.html) for more information.

**Note:** if `shouldComponentUpdate()` returns false when data has actually changed, React can't keep your UI in sync. Be sure you know what you're doing while using it, and only use this function when you have a noticeable performance problem. Don't underestimate how fast JavaScript is relative to the DOM.
86 changes: 86 additions & 0 deletions docs/docs/refactor/05-building-effective-reusable-components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
## Build reusable component libraries!

When designing interfaces, break down the common design elements (buttons, form fields, layout components, etc) into reusable components with well-defined interfaces. That way, the next time you need to build some UI you can write much less code, which means faster development time, less bugs, and less bytes down the wire.

## Prop validation

As your app grows it's helpful to ensure that your components are used correctly. We do this using `propTypes`.

** TODO zpao **

## Transferring props: a shortcut

A common type of React component is one that extends a basic HTML 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. React provides `transferPropsTo()` to do just this.

```javascript
/** @jsx React.DOM */

var CheckLink = React.createClass({
render: function() {
// transferPropsTo() will take any props pased to CheckLink
// and copy them to <a>
return this.transferPropsTo(<a>{''}{this.props.children}</a>);
}
});

React.renderComponent(
<CheckLink href="javascript:alert('Hello, world!');">
Click here!
</CheckLink>,
document.getElementById('example')
);
```

## Mixins

Components are the best way to reuse code in React, but sometimes very different components may share some common functionality. These are sometimes called [cross-cutting concerns](http://en.wikipedia.org/wiki/Cross-cutting_concern). React provides `mixins` to solve this problem.

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](./06-working-with-the-browser.html) 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.

```javascript
/** @jsx React.DOM */

var SetIntervalMixin = {
componentWillMount: function() {
this.intervals = [];
},
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
},
componentWillUnmount: function() {
this.intervals.map(clearInterval);

This comment has been minimized.

Copy link
@hura

hura Jan 2, 2014

Shouldn't clearInterval be defined somewhere in this example?

This comment has been minimized.

Copy link
@sophiebits

sophiebits Jan 2, 2014

Collaborator

No -- like setTimeout, it's a browser builtin: https://developer.mozilla.org/en-US/docs/Web/API/Window.clearInterval.

}
};

var TickTock = React.createClass({
mixins: [SetIntervalMixin], // Use the mixin
getInitialState: function() {
return {seconds: 0};
},
componentDidMount: function() {
this.setInterval(this.tick, 1000); // Call a method on the mixin
},
tick: function() {
this.setState({seconds: this.state.seconds + 1});
},
render: function() {
return (
<p>
React has been running for {this.state.seconds} seconds.
</p>
);
}
});

React.renderComponent(
<TickTock />,
document.getElementById('example')
);
```

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.

## Testing

**TODO: benjamn**

119 changes: 119 additions & 0 deletions docs/docs/refactor/06-forms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Forms

Form components such as `<input>`, `<textarea>`, and `<option>` differ from other native components because they can be mutated via user interactions. These components provide interfaces that make it easier to manage forms in response to user interactions.

## Interactive Props

Form components support a few props that are affected via user interactions:

- `value`, supported by `<input>` and `<textarea>` components.
- `checked`, supported by `<input>` components of type `checkbox` or `radio`.
- `selected`, supported by `<option>` components.

In HTML, the value of `<textarea>` is set via children. In React, you should use `value` instead.

Form components allow listening for changes by setting a callback to the `onChange` prop. The `onChange` prop works across browsers to fire in response to user interactions when:

- The `value` of `<input>` or `<textarea>` changes.
- The `checked` state of `<input>` changes.
- The `selected` state of `<option>` changes.

Like all DOM events, the `onChange` prop is supported on all native components and can be used to listen to bubbled change events.

## Controlled Components

An `<input>` with `value` set is a *controlled* component. In a controlled `<input>`, the value of the rendered element will always reflect the `value` prop. For example:

```javascript
render: function() {
return <input type="text" value="Hello!" />;
}
```

This will render an input that always has a value of `Hello!`. Any user input will have no effect on the rendered element because React has declared the value to be `Hello!`. If you wanted to update the value in response to user input, you could use the `onChange` event:

```javascript
getInitialState: function() {
return {value: 'Hello!'};
},
render: function() {
var value = this.state.value;
return <input type="text" value={value} onChange={this.handleChange} />;
},
handleChange: function(event) {
this.setState({value: event.target.value});
}
```

In this example, we are simply accepting the newest value provided by the user and updating the `value` prop of the `<input>` component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. For example:

```javascript
handleChange: function(event) {
this.setState({value: event.target.value.substr(0, 140)});
}
```

This would accept user input but truncate the value to the first 140 characters.

## Uncontrolled Components

An `<input>` that does not supply a `value` (or sets it to `null`) is an *uncontrolled* component. In an uncontrolled `<input>`, the value of the rendered element will reflect the user's input. For example:

```javascript
render: function() {
return <input type="text" />;
}
```

This will render an input that starts off with an empty value. Any user input will be immediately reflected by the rendered element. If you wanted to listen to updates to the value, you could use the `onChange` event just like you can with controlled components.

If you want to initialize the component with a non-empty value, you can supply a `defaultValue` prop. For example:

```javascript
render: function() {
return <input type="text" defaultValue="Hello!" />;
}
```

This example will function much like the **Controlled Components** example above.

Likewise, `<input>` supports `defaultChecked` and `<option>` supports `defaultSelected`.

## Advanced Topics

### Why controlled components?

Using form components such as `<input>` in React presents a challenge that is absent when writing traditional form HTML. For example, in HTML:

```html
<input type="text" name="title" value="Untitled" />
```

This renders an input *initialized* with the value, `Untitled`. When the user updates the input, the node's value *property* will change. However, `node.getAttribute('value')` will still return the value used at initialization time, `Untitled`.

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() {
return <input type="text" name="title" value="Untitled" />;
}
```

Since this method describes the view at any point in time, the value of the text input should *always* be `Untitled`.

### Why textarea value?

In HTML, the value of `<textarea>` is usually set using its children:

```html
<!-- counterexample: DO NOT DO THIS! -->

This comment has been minimized.

Copy link
@gajus

gajus Jul 19, 2015

Contributor

"counterexample" is not a suitable word here: "a counterexample is an exception to a proposed general rule or law." (from Oxford dictionary). Just "DO NOT DO THIS!".

This comment has been minimized.

Copy link
@quantizor

quantizor Jul 20, 2015

Contributor

'antipattern' is the word most frequently used by the developer community

This comment has been minimized.

Copy link
@sophiebits

sophiebits Jul 20, 2015

Collaborator

Thanks, changed in d13fafa.

<textarea name="description">This is the description.</textarea>
```

For HTML, this easily allows developers to supply multiline values. However, since React is JavaScript, we do not have string limitations and can use `\n` if we want newlines. In a world where we have `value` and `defaultValue`, it is ambiguous what role children play. For this reason, you should not use children when setting `<textarea>` values:

```javascript
<textarea name="description" value="This is a description." />
```

If you *do* decide to use children, they will behave like `defaultValue`.

0 comments on commit bb3bd76

Please sign in to comment.