REACT CONCURRENT MODE
- development
- react
Previous workarounds
Debounce – Only update the list after the user stops typing Throttle – Update the list with a certain maximum frequency
Similar to git branches
Concurrent Mode is like React working on git branches.
Eg:- Navigating between two screens in an app
In React Concurrent Mode, we can tell React to keep showing the old screen(like another git branch), fully interactive, with an inline loading indicator. And when the new screen is ready, React can take us to it.
Concurrency
CPU
For CPU-bound updates like creating DOM nodes and running component code, concurrency means that a more urgent update can “interrupt” rendering that has already started.
For IO-bound updates like fetching code or data from the network, concurrency means that React can start rendering in memory even before all the data arrives, and skip showing jarring empty loading states.
Install
Install the experimental version of react and react-dom.
yarn add react@experimental react-dom@experimental
Run your app, run your build, run your tests/type checking and make sure there are no issues.
Likely issues:
- String Refs, Legacy Context, or findDOMNode
- All the lifecycle methods that have the
unsafe_prefix
Enable Concurrent Mode:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './app';
const rootElement = document.getElementById('root');
// ReactDOM.render(<App />, rootEl)
const root = ReactDOM.createRoot(rootElement);
root.render(<App />);
Try Concurrent Mode
Concurrent Mode enables two new features:
- Time slicing
- Suspense for everything asynchronous
Let’s create an app for testing out these features with create-react-app.
Experimental
Write a function for creating an actor when an actor name is provided in the input field:
function createActor(name) {
let status = 'pending';
let result;
let suspender = getActor(name).then(
(name) => {
status = 'success';
result = name;
},
(error) => {
status = 'error';
result = error;
},
);
return {
read() {
if (status === 'pending') throw suspender;
if (status === 'error') throw result;
if (status === 'success') return result;
},
};
}
Let’s create a function to imitate an HTTP request:
function getActor(name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`Your favorite actor is ${name}!`);
// Uncomment below to test rejecting instead
// reject(new Error(`Oops! could not load message for ${name}`))
}, 1000);
});
}
Now we can create a form so we can use the above functions
function Form() {
const [actor, setActor] = useState(null);
const [startTransition, isPending] = useTransition({
timeoutMs: 3000,
});
function handleSubmit(event) {
event.preventDefault();
const name = event.target.elements.nameInput.value;
startTransition(() => {
setActor(createActor(name));
});
}
return (
<div>
<form onSubmit={handleSubmit}>
<label htmlFor="nameInput">Name</label>
<input id="nameInput" />
<button type="submit">Submit</button>
</form>
<Suspense fallback={<p>Loading...</p>}>
::message{(type = 'info')}
::
</Suspense>
</div>
);
}
function Message({ actor, isPending }) {
return (
<p style={{ opacity: isPending ? 0.4 : 1 }}>
{actor ? actor.read() : 'Please provide an actor'}
</p>
);
}
Here is the full example of React concurrent mode in action: