Replacing and rendering the whole real DOM is costly!
Virtual DOM is a representation of the actual DOM
Its purpose is to identify which parts of the real DOM need to be changed upon changes, by comparing the new virtual DOM result against the previous one.
The delta then gets applied on the real DOM.
E.g. only one element gets updated within a long list instead of
the whole list.
ReactDOM.render(
<IntlProvider locale={usersLocale} messages={translationsForUsersLocale}>
<App />
</IntlProvider>,
document.getElementById('container')
)
const { formatMessage } = useIntl();
…
return (
<h1>{formatMessage({ id: 'myOptionalPersonallyDefinedKey', description: 'title' })}</h1>
<h2><FormattedMessage
id="myOptionalPersonallyDefinedKey"
defaultMessage="Today is {ts, date, ::yyyyMMdd}"
values={{ts: Date.now()}}
/></h2>
);
Use virtualization as a "last resort", usually there are other places which are easier to fix.
React Lazy / Suspense
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
);
}
It is the closest thing to a mocking server without having to
create one.
—
Mock Service Worker Docs
npm install msw --save-dev
Source: https://mswjs.io/docs/
The node-request-interceptor library is used to intercept HTTP requests.
src/mocks/server.ts
import { setupServer } from 'msw/node' import { handlers } from './handlers' /* This configures a request mocking server with the given request handlers. */ export const server = setupServer(...handlers);
src/setupTests.ts
import { server } from "./mocks/server.js"; /* Establish API mocking before all tests. */ beforeAll(() => server.listen()); /* Reset any request handlers that we may add during the tests, so they don't affect other tests. */ afterEach(() => server.resetHandlers()); /* Clean up after the tests are finished. */ afterAll(() => server.close());
src/handlers.ts
const handlers = [ rest.get( "/api/v2/pokemon?limit=50", (_, res, ctx) => res(ctx.json({ results: [ { name: "Pikachu", url: "…" }, … ] })) ) ]; export { handlers };
Or: How to break out of Virtual DOM
Refs permit to obtain a reference to a real dom element
import { useRef, useEffect } from "react";
export function MyComponent() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return (
<input ref={inputRef} />
);
}
Automatically set focus on page load
function CustomInput({ ref }) {
return <input ref={ref} />;
}
<CustomInput ref={ref} />
Does not work! – ref is a special prop (the other one is key)
const CustomInput = forwardRef<HTMLInputElement, Props>((props, ref) => {
return <input ref={ref} />;
});
CustomInput.displayName = "CustomInput";
<CustomInput ref={ref} />
The browserslist configuration controls the outputted JavaScript so that the emitted code will be compatible with the browsers specified.
Polyfills still need to be added manually!
Your code is always consistent, as is the code from the rest of your team. No more bikeshedding!
Let's install it either locally npm i -D prettier or run it with npx prettier .
Prettier is heavily opinionated. Luckily there are a lot of options to customize it to your liking.
Add a .prettierrc.js file to your project:
module.exports = {
endOfLine: 'lf',
singleQuote: true,
trailingComma: 'all',
quoteProps: 'consistent',
}
Add an npm script to the package.json :
"scripts": {
"pretty": "prettier --write \"src/**/*.{js,json,
yml,yaml,css,scss,ts,tsx,md}\"",
},
Multiple configurations and plugins can be configured in the extends field value.
If multiple configurations or plugins specify contradicting values for the same rule, the latter will be applied.
Rules can be overridden in the rules field value.
class HelloWorld extends React.Component {
render() {
return (
<div>Hello World</div>
);
}
}
class HelloWorld extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.setState({ date: new Date() }),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
render() {
return (
<>
<h1>Hello World, it is:</h1>
<h2>{this.state.date.toLocaleTimeString()}</h2>
</>
);
}
}
function MyComponent() { return <ErrorBoundary> <MyWidget /> </ErrorBoundary>; }
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { /* Update state so the next render will show the fallback UI. */ return { hasError: true }; } render() { if (this.state.hasError) { /* You can render any custom fallback UI */ return <h1>Something went wrong.</h1>; } return this.props.children; } }
class ErrorBoundary extends React.Component { constructor(props) { super(props); } componentDidCatch(error, errorInfo) { /* You can also log the error to an error reporting service */ logErrorToMyService(error, errorInfo); } render() { return this.props.children; } }
One option: framer-motion
Source: Plasmic Blog – How React server components work: an in-depth guide