[Try it on CodePen.](http://codepen.io/gaearon/pen/ozqNOV?editors=0010)
[Try it on CodePen.](https://codepen.io/gaearon/pen/ozqNOV?editors=0010)
Anything inside the `<FancyBorder>` JSX tag gets passed into the `FancyBorder` component as a `children` prop. Since `FancyBorder` renders `{props.children}` inside a `<div>`, the passed elements appear in the final output.
@ -77,7 +77,7 @@ function App() {
}
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/gwZOJp?editors=0010)
[Try it on CodePen.](https://codepen.io/gaearon/pen/gwZOJp?editors=0010)
React elements like `<Contacts />` and `<Chat />` are just objects, so you can pass them as props like any other data.
@ -110,7 +110,7 @@ function WelcomeDialog() {
}
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/kkEaOZ?editors=0010)
[Try it on CodePen.](https://codepen.io/gaearon/pen/kkEaOZ?editors=0010)
Composition works equally well for components defined as classes:
@ -160,7 +160,7 @@ class SignUpDialog extends React.Component {
}
```
[Try it on CodePen.](http://codepen.io/gaearon/pen/gwZbYa?editors=0010)
[Try it on CodePen.](https://codepen.io/gaearon/pen/gwZbYa?editors=0010)
@ -56,7 +56,7 @@ class Calculator extends React.Component {
}
```
[Try it on CodePen.](http://codepen.io/valscion/pen/VpZJRZ?editors=0010)
[Try it on CodePen.](https://codepen.io/gaearon/pen/ZXeOBm?editors=0010)
## Adding a Second Input
@ -110,7 +110,7 @@ class Calculator extends React.Component {
}
```
[Try it on CodePen.](http://codepen.io/valscion/pen/GWKbao?editors=0010)
[Try it on CodePen.](https://codepen.io/gaearon/pen/jGBryx?editors=0010)
We have two inputs now, but when you enter the temperature in one of them, the other doesn't update. This contradicts our requirement: we want to keep them in sync.
@ -296,7 +296,7 @@ class Calculator extends React.Component {
}
```
[Try it on CodePen.](http://codepen.io/valscion/pen/jBNjja?editors=0010)
[Try it on CodePen.](https://codepen.io/gaearon/pen/WZpxpz?editors=0010)
Now, no matter which input you edit, `this.state.temperature` and `this.state.scale` in the `Calculator` get updated. One of the inputs gets the value as is, so any user input is preserved, and the other input value is always recalculated based on it.
@ -77,8 +100,9 @@ class Parent extends React.Component {
}
handleClick() {
// This will fire when the button in Child is clicked, updating Parent's state,
// even though Child is not a direct descendant in the DOM.
// This will fire when the button in Child is clicked,
// updating Parent's state, even though button
// is not direct descendant in the DOM.
this.setState(prevState => ({
clicks: prevState.clicks + 1
}));
@ -86,10 +110,17 @@ class Parent extends React.Component {
render() {
return (
<divonClick={this.onClick}>
<divonClick={this.handleClick}>
<p>Number of clicks: {this.state.clicks}</p>
<p>Open up the browser DevTools to observe that the button is not a child the div with onClick handler.</p>
{ReactDOM.createPortal(<Child/>, modalRoot)}
<p>
Open up the browser DevTools
to observe that the button
is not a child the div
with onClick handler.
</p>
<Modal>
<Child/>
</Modal>
</div>
);
}
@ -105,10 +136,9 @@ function Child() {
);
}
ReactDOM.render(<Parent/>, appRoot);
```
[Try this example on CodePen](https://codepen.io/gaearon/pen/jGBWpE).
[Try it on CodePen.](https://codepen.io/gaearon/pen/jGBWpE).
Catching an event bubbling up from a portal in a parent component allows the development of more flexible abstractions that are not inherently reliant on portals. For example, if you render a `<Modal />` component, the parent can capture its events regardless of whether it's implemented using portals.
@ -98,7 +98,19 @@ The `value` attribute is supported by `<input>` and `<textarea>` components. You
## All Supported HTML Attributes
React supports all `data-*` and `aria-*` attributes as well as these attributes:
As of React 16, any standard [or custom](/react/blog/2017/09/08/dom-attributes-in-react-16.html) DOM attributes are fully supported.
React has always provided a JavaScript-centric API to the DOM. Since React components often take both custom and DOM-related props, React uses the `camelCase` convention just like the DOM APIs:
```js
<divtabIndex="-1"/> // Just like node.tabIndex DOM API
<divclassName="Button"/> // Just like node.className DOM API
<inputreadOnly={true}/> // Just like node.readOnly DOM API
```
These props work similarly to the corresponding HTML attributes, with the exception of the special cases documented above.
Some of the DOM attributes supported by React include:
```
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
@ -61,7 +61,7 @@ Now that we've identified the components in our mock, let's arrange them into a
## Step 2: Build A Static Version in React
<pdata-height="600"data-theme-id="0"data-slug-hash="vXpAgj"data-default-tab="js"data-user="lacker"data-embed-version="2"class="codepen">See the Pen <ahref="http://codepen.io/lacker/pen/vXpAgj/">Thinking In React: Step 2</a> on <ahref="http://codepen.io">CodePen</a>.</p>
<pdata-height="600"data-theme-id="0"data-slug-hash="BwWzwm"data-default-tab="js"data-user="lacker"data-embed-version="2"class="codepen">See the Pen <ahref="https://codepen.io/gaearon/pen/BwWzwm">Thinking In React: Step 2</a> on <ahref="http://codepen.io">CodePen</a>.</p>
Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why.
@ -106,7 +106,7 @@ So finally, our state is:
## Step 4: Identify Where Your State Should Live
<pdata-height="600"data-theme-id="0"data-slug-hash="ORzEkG"data-default-tab="js"data-user="lacker"data-embed-version="2"class="codepen">See the Pen <ahref="http://codepen.io/lacker/pen/ORzEkG/">Thinking In React: Step 4</a> by Kevin Lacker (<ahref="http://codepen.io/lacker">@lacker</a>) on <ahref="http://codepen.io">CodePen</a>.</p>
<pdata-height="600"data-theme-id="0"data-slug-hash="qPrNQZ"data-default-tab="js"data-user="lacker"data-embed-version="2"class="codepen">See the Pen <ahref="https://codepen.io/gaearon/pen/qPrNQZ">Thinking In React: Step 4</a> on <ahref="http://codepen.io">CodePen</a>.</p>
OK, so we've identified what the minimal set of app state is. Next, we need to identify which component mutates, or *owns*, this state.
@ -132,7 +132,7 @@ You can start seeing how your application will behave: set `filterText` to `"bal
## Step 5: Add Inverse Data Flow
<pdata-height="600"data-theme-id="0"data-slug-hash="qRqmjd"data-default-tab="js,result"data-user="rohan10"data-embed-version="2"data-pen-title="Thinking In React: Step 5"class="codepen">See the Pen <ahref="http://codepen.io/rohan10/pen/qRqmjd">Thinking In React: Step 5</a> on <ahref="http://codepen.io">CodePen</a>.</p>
<pdata-height="600"data-theme-id="0"data-slug-hash="LzWZvb"data-default-tab="js,result"data-user="rohan10"data-embed-version="2"data-pen-title="Thinking In React: Step 5"class="codepen">See the Pen <ahref="https://codepen.io/gaearon/pen/LzWZvb">Thinking In React: Step 5</a> on <ahref="http://codepen.io">CodePen</a>.</p>
So far, we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in `FilterableProductTable`.