Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ module.system.node.resolve_dirname=src

esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
unsafe.enable_getters_and_setters=true

munge_underscores=false

Expand All @@ -32,4 +31,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError

[version]
^0.56.0
^0.87.0
26 changes: 0 additions & 26 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,32 +56,6 @@ In particular, you should prefer named `function` declarations over `const myFun

#### Don't use features that aren't standardized yet.

For example, **don't** write this:

```js
class MyComponent extends React.Component {
state = {value: ''};
handleChange = (e) => {
this.setState({value: e.target.value});
};
}
```

Instead, **do** write this:

```js
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {value: ''};
}
handleChange(e) {
this.setState({value: e.target.value});
}
}
```

Ignore this rule if you're specifically describing an experimental proposal. Make sure to mention its experimental nature in the code and in the surrounding text.

### Style
Expand Down
190 changes: 78 additions & 112 deletions content/docs/accessibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,39 +169,35 @@ To set focus in React, we can use [Refs to DOM elements](/docs/refs-and-the-dom.

Using this, we first create a ref to an element in the JSX of a component class:

```javascript{4-5,8-9,13}
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
// Create a ref to store the textInput DOM element
this.textInput = React.createRef();
}
render() {
```javascript{2-3,5-6,10}
function CustomTextInput() {
// Create a ref to store the textInput DOM element
const textInput = useRef();

// Use the `ref` callback to store a reference to the text input DOM
// element in an instance field (for example, this.textInput).
return (
<input
type="text"
ref={this.textInput}
/>
);
}
// element in a ref field (for example, textInput).
return (
<input
type="text"
ref={textInput}
/>
);
}
```

Then we can focus it elsewhere in our component when needed:

```javascript
focus() {
function focus() {
// Explicitly focus the text input using the raw DOM API
// Note: we're accessing "current" to get the DOM node
this.textInput.current.focus();
textInput.current.focus();
}
```

Sometimes a parent component needs to set focus to an element in a child component. We can do this by [exposing DOM refs to parent components](/docs/refs-and-the-dom.html#exposing-dom-refs-to-parent-components) through a special prop on the child component that forwards the parent's ref to the child's DOM node.

```javascript{4,12,16}
```javascript{4,10,13}
function CustomTextInput(props) {
return (
<div>
Expand All @@ -210,20 +206,16 @@ function CustomTextInput(props) {
);
}

class Parent extends React.Component {
constructor(props) {
super(props);
this.inputElement = React.createRef();
}
render() {
return (
<CustomTextInput inputRef={this.inputElement} />
);
}
function Parent() {
const inputElement = useRef();

return (
<CustomTextInput inputRef={inputElement} />
);
}

// Now you can set focus when required.
this.inputElement.current.focus();
inputElement.current.focus();
```

When using a HOC to extend components, it is recommended to [forward the ref](/docs/forwarding-refs.html) to the wrapped component using the `forwardRef` function of React. If a third party HOC does not implement ref forwarding, the above pattern can still be used as a fallback.
Expand All @@ -246,52 +238,40 @@ To illustrate this, let's look at a prolific example of broken accessibility cau

This is typically implemented by attaching a `click` event to the `window` object that closes the popover:

```javascript{12-14,26-30}
class OuterClickExample extends React.Component {
constructor(props) {
super(props);

this.state = { isOpen: false };
this.toggleContainer = React.createRef();

this.onClickHandler = this.onClickHandler.bind(this);
this.onClickOutsideHandler = this.onClickOutsideHandler.bind(this);
}
```javascript{4-10,16-20}
function OuterClickExample() {
const [isOpen, setIsOpen] = useState(false);

componentDidMount() {
window.addEventListener('click', this.onClickOutsideHandler);
}
useEffect(() => {
window.addEventListener('click', onClickOutsideHandler);

componentWillUnmount() {
window.removeEventListener('click', this.onClickOutsideHandler);
}
return () => {
window.removeEventListener('click', onClickOutsideHandler);
};
}, []);

onClickHandler() {
this.setState(currentState => ({
isOpen: !currentState.isOpen
}));
function onClickHandler() {
setIsOpen(isOpen => !isOpen);
}

onClickOutsideHandler(event) {
if (this.state.isOpen && !this.toggleContainer.current.contains(event.target)) {
this.setState({ isOpen: false });
function onClickOutsideHandler(event) {
if (!toggleContainer.current.contains(event.target)) {
setIsOpen(false);
}
}

render() {
return (
<div ref={this.toggleContainer}>
<button onClick={this.onClickHandler}>Select an option</button>
{this.state.isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
return (
<div ref={toggleContainer}>
<button onClick={onClickHandler}>Select an option</button>
{isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
```

Expand All @@ -301,63 +281,49 @@ This may work fine for users with pointer devices, such as a mouse, but operatin

The same functionality can be achieved by using appropriate event handlers instead, such as `onBlur` and `onFocus`:

```javascript{19-29,31-34,37-38,40-41}
class BlurExample extends React.Component {
constructor(props) {
super(props);

this.state = { isOpen: false };
this.timeOutId = null;
```javascript{9-17,19-22,24-25,27-28}
function BlurExample() {
const [isOpen, setIsOpen] = useState(false);
const timeOutId = useRef();

this.onClickHandler = this.onClickHandler.bind(this);
this.onBlurHandler = this.onBlurHandler.bind(this);
this.onFocusHandler = this.onFocusHandler.bind(this);
}

onClickHandler() {
this.setState(currentState => ({
isOpen: !currentState.isOpen
}));
function onClickHandler() {
setIsOpen(isOpen => !isOpen);
}

// We close the popover on the next tick by using setTimeout.
// This is necessary because we need to first check if
// another child of the element has received focus as
// the blur event fires prior to the new focus event.
onBlurHandler() {
this.timeOutId = setTimeout(() => {
this.setState({
isOpen: false
});
function onBlurHandler() {
timeOutId.current = setTimeout(() => {
setIsOpen(false);
});
}

// If a child receives focus, do not close the popover.
onFocusHandler() {
clearTimeout(this.timeOutId);
function onFocusHandler() {
clearTimeout(timeOutId.current);
}

render() {
// React assists us by bubbling the blur and
// focus events to the parent.
return (
<div onBlur={this.onBlurHandler}
onFocus={this.onFocusHandler}>
<button onClick={this.onClickHandler}
aria-haspopup="true"
aria-expanded={this.state.isOpen}>
Select an option
</button>
{this.state.isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
// React assists us by bubbling the blur and
// focus events to the parent.
return (
<div onBlur={onBlurHandler}
onFocus={onFocusHandler}>
<button onClick={onClickHandler}
aria-haspopup="true"
aria-expanded={isOpen}>
Select an option
</button>
{isOpen && (
<ul>
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
)}
</div>
);
}
```

Expand Down
4 changes: 2 additions & 2 deletions content/docs/add-react-to-a-website.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const e = React.createElement;
// Display a "Like" <button>
return e(
'button',
{ onClick: () => this.setState({ liked: true }) },
{ onClick: () => setLiked(true) },
'Like'
);
```
Expand All @@ -141,7 +141,7 @@ However, React also offers an option to use [JSX](/docs/introducing-jsx.html) in
```js
// Display a "Like" <button>
return (
<button onClick={() => this.setState({ liked: true })}>
<button onClick={() => setLiked(true)}>
Like
</button>
);
Expand Down
16 changes: 6 additions & 10 deletions content/docs/codebase-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: Codebase Overview
layout: contributing
permalink: docs/codebase-overview.html
prev: how-to-contribute.html
next: implementation-notes.html
next: design-principles.html
redirect_from:
- "contributing/codebase-overview.html"
---
Expand Down Expand Up @@ -189,16 +189,12 @@ The only other officially supported renderer is [`react-art`](https://github.com

### Reconcilers {#reconcilers}

Even vastly different renderers like React DOM and React Native need to share a lot of logic. In particular, the [reconciliation](/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.
Even vastly different renderers like React DOM and React Native need to share a lot of logic. In particular, the [reconciliation](/docs/reconciliation.html) algorithm should be as similar as possible so that declarative rendering, custom components, state, hooks, 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.
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 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 {#stack-reconciler}

The "stack" reconciler is the implementation powering React 15 and earlier. We have since stopped using it, but it is documented in detail in the [next section](/docs/implementation-notes.html).

### Fiber Reconciler {#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 has been the default reconciler since React 16.
Expand All @@ -208,7 +204,7 @@ 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()`.
* Ability to return multiple elements from components.
* Better support for error boundaries.

You can read more about React Fiber Architecture [here](https://github.com/acdlite/react-fiber-architecture) and [here](https://blog.ag-grid.com/inside-fiber-an-in-depth-overview-of-the-new-reconciliation-algorithm-in-react). While it has shipped with React 16, the async features are not enabled by default yet.
Expand All @@ -221,6 +217,6 @@ React implements a synthetic event system which is agnostic of the renderers and

There is a [video with a deep code dive into it](https://www.youtube.com/watch?v=dRo_egw7tBc) (66 mins).

### What Next? {#what-next}
### Next Steps {#next-steps}

Read the [next section](/docs/implementation-notes.html) to learn about the pre-React 16 implementation of reconciler in more detail. We haven't documented the internals of the new reconciler yet.
Read the [next section](/docs/design-principles.html) to learn about the guiding principles we use for React development.
Loading