Hi, Gleb Kotovsky is here!
Today I wanna talk about Virtual DOM, specifically - React Virtual DOM
So, the virtual DOM (Virtual Document Object Model) is a cool programming idea that keeps a "virtual" version of a user interface in memory. This version syncs up with the browser's DOM (Document Object Model) using a library.
You’ll find the virtual DOM is a big part of many JavaScript front-end frameworks, and it’s one of the reasons they’re so efficient. In this article, we're going to dive into how the virtual DOM works in React and why it’s important for the library.
When a webpage loads in a browser, it typically receives an HTML document from the server. The browser then builds a logical, tree-like structure from this HTML to render the requested page for the user. This structure is known as the DOM.
The Document Object Model (DOM) represents a logical tree that describes a document. Each branch of the tree ends in a node , which contains an object . Because the browser parses the document into this tree structure, there is a need for methods that allow for programmatic access to the tree, enabling modifications to the document's structure, style, or content. This necessity led to the development of the DOM API, which offers these methods for manipulating the nodes representing the elements in the tree.
To optimize re-rendering in websites and applications, many JavaScript frameworks offer different strategies. However, React employs the concept of the virtual DOM.
The virtual DOM in React represents the user interface as a "virtual" tree structure, where each element is a node containing an object. This representation is maintained in memory and synchronized with the browser's DOM through React's React DOM library.
When React and many other famous frameworks uses Virtual DOM, Svelte meanwhile has no Virtual DOM. Svelte works directly with the DOM in the browser and modifies it as needed.
Here's a simple example to illustrate the Virtual DOM in a React component:
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); const increment = () => setCount(count 1); return (); }Count: {count}
In this example:
After the component is first rendered and the state is count: 0, the actual DOM will look like this:
Counter
Count: 0
Here's a simple example to illustrate the Virtual DOM in a React component, starting with the component definition:
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); const increment = () => setCount(count 1); return (); }Counter
Count: {count}
When the component is first rendered, React calls the Counter function.
useState(0) initializes the component's state to 0.
React generates a Virtual DOM tree using the component's returned JSX structure. This tree is a lightweight representation of the UI.
For the initial render, the Virtual DOM might look like this:
{ "type": "div", "props": { "children": [ { "type": "h1", "props": { "children": "Counter" } }, { "type": "p", "props": { "children": "Count: 0" } }, { "type": "button", "props": { "children": "Increment" } } ] } }
React then takes this Virtual DOM and calculates what changes need to be made to the actual DOM. In this case, it creates the following HTML:
Counter
Count: 0
When a user clicks the "Increment" button, the following steps occur:
The button's onClick event triggers the increment function, calling setCount(count 1).
The component's state is updated, which causes React to know that it needs to re-render the component with the new state.
React calls the Counter function again due to the state change.
A new Virtual DOM tree is created reflecting the updated state:
{ "type": "div", "props": { "children": [ { "type": "h1", "props": { "children": "Counter" } }, { "type": "p", "props": { "children": "Count: 1" } }, { "type": "button", "props": { "children": "Increment" } } ] } }
React compares the new Virtual DOM with the previous Virtual DOM. It identifies what has changed—in this case, the text in the
tag has changed from "Count: 0" to "Count: 1".
Only the parts of the real DOM that have changed are updated. In this case, React updates the real DOM to reflect the new count:
Counter
Count: 1
If multiple state updates occur in rapid succession (e.g., multiple button clicks), React may batch these updates together for efficiency, minimizing the number of re-renders and DOM updates.
const MyComponent = React.memo(({ value }) => { console.log('Rendered: ', value); return{value}; });
Legacy: Use shouldComponentUpdate in class components:
class MyClassComponent extends React.Component { shouldComponentUpdate(nextProps) { return nextProps.value !== this.props.value; } render() { return{this.props.value}; } }
const items = ['Apple', 'Banana', 'Cherry']; return (
const [state, setState] = useState({ name: '', age: 0, }); const updateAge = (newAge) => { setState(prevState => ({ ...prevState, age: newAge })); };
const increment = useCallback(() => { setCount(c => c 1); }, []); // Only recreate the function if dependencies change
const CountContext = React.createContext(); const ParentComponent = () => { const [count, setCount] = useState(0); return (); }; const ChildComponent = () => { const { count, setCount } = useContext(CountContext); return setCount(count 1)}>Count: {count}; };
const ChildComponent = React.memo(({ count }) => { returnCount: {count}; });
const LazyComponent = React.lazy(() => import('./LazyComponent')); const App = () => (Loading...}> );
useEffect(() => { const timer = setTimeout(() => { console.log('Time elapsed'); }, 1000); return () => clearTimeout(timer); // Cleanup on unmount or if dependencies change }, [dependencies]); // Replace with actual dependency
const ParentComponent = () => { const [name, setName] = useState('John'); return; }; const ChildComponent = ({ name, setName }) => ( );{name}
const AccessibleButton = () => ( );
To wrap things up, React’s Virtual DOM is a fantastic feature that really boosts the performance of your web applications. By creating a lightweight version of the actual DOM, React can make updates more efficiently, avoiding the slowdowns that come with direct DOM manipulation.
That said, it’s important to watch out for common issues like excessive re-renders, poor key management in lists, and mixing up state and props. By keeping some best practices in mind—like using memoization, deploying context for handling state, and managing side effects wisely—you can get the most out of React and keep your apps running smoothly.
Happy hacking!
1) https://www.geeksforgeeks.org/reactjs-virtual-dom/
2) https://svelte.dev/blog/virtual-dom-is-pure-overhead
3) https://refine.dev/blog/react-virtual-dom/#introduction
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3