开源日报每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,坚持阅读《开源日报》,保持每日学习的好习惯。
2024年1月24日,开源日报第1084期:
今日推荐开源项目:《cypress》
今日推荐英文原文:《From My Experience: useEffect vs useLayoutEffect in React》
开源项目
今日推荐开源项目:《cypress》传送门:项目链接
推荐理由: 快速、简便且可靠的测试适用于在浏览器中运行的任何内容
网站直达:cypress.io
英文原文
今日推荐英文原文:From My Experience: useEffect vs useLayoutEffect in React
推荐理由:useEffect 和 useLayoutEffect 是 React 中处理副作用的关键 Hooks。前者适用于大多数场景,执行于浏览器绘制后,用于数据获取和订阅,而LayoutEffect用于需要在 DOM 变更之前同步操作的场景
From My Experience: useEffect vs useLayoutEffect in ReactIntroduction 🌟
With the introduction of hooks in React 16.8, the landscape of writing functional components changed dramatically. Among these, useEffect
and useLayoutEffect
are particularly important for handling side effects in your code. They might look similar at first, but there are some important differences between them. In this blog, we'll look at these differences in a clear and straightforward way. We'll help you understand when to use useEffect
and when useLayoutEffect
might be a better choice for your React projects.
Let's get started on this practical exploration of these two essential React hooks.
What is useEffect? 🔍
useEffect
is a React hook that allows you to perform side effects in your functional components. Side effects are essentially any operations that affect something outside the scope of the function being executed. This can include data fetching, subscriptions, manually changing the DOM, and more.
Remember, 99% of the time,
useEffect
is the hook you'll want to use.
How to Use useEffect: 🚀
When you use useEffect
, you tell React to do something after the render. React will remember the function you passed, and call it later after performing the DOM updates.
Syntax of useEffect:
useEffect(() => {
// Code for your side effect goes here.
}, [dependencies]);
The second argument, [dependencies]
, is an array of dependencies. React will only re-run the side effect if one of the dependencies has changed. If you pass an empty array ([]
), the side effect runs once after the initial render, making it similar to componentDidMount
in class components.
What is useLayoutEffect? 🤔
useLayoutEffect
is another React hook that is similar to useEffect
but with a key difference in its execution timing. It is used for operations that need to synchronize with the DOM, such as directly manipulating the DOM or adjusting the layout before the browser paints.
When to Use useLayoutEffect: 📐
useLayoutEffect
should be used when you need to make DOM changes before the screen is updated. This is crucial in scenarios where you want to avoid visual glitches, like flickering, that can occur if you manipulate the DOM after it has been painted on the screen.
Syntax of useLayoutEffect:
useLayoutEffect(() => {
// Code that interacts with the DOM.
}, [dependencies]);
Like useEffect
, it also takes a dependency array as the second argument.
Comparing useEffect and useLayoutEffect in Action ⚖️
After exploring useEffect
and useLayoutEffect
separately, it's helpful to see them in action within the same component. This comparison will give us a clearer understanding of their execution order and behavior.
Let’s create a single functional component that includes both useEffect
and useLayoutEffect
. We will add console logs to each hook to observe the order in which they execute.
import React, { useEffect, useLayoutEffect } from 'react';
const Home = () => {
useLayoutEffect(() => {
console.log('useLayoutEffect - Runs first, but after DOM mutations');
}, []);
useEffect(() => {
console.log('useEffect - Runs second, after the browser has painted');
}, []);
return (
<div>Hello, React Hooks!</div>
);
};
export default Home;
In this component, we have both useLayoutEffect
and useEffect
with empty dependency arrays, meaning they should run after the initial render.
useEffect vs useLayoutEffect
- useLayoutEffect: This hook runs first. It is fired after all DOM mutations are complete but before the browser has had a chance to paint. This makes it ideal for any DOM manipulations or calculations that need to happen right after the DOM updates but before the user sees anything. The console log inside
useLayoutEffect
will be the first one to appear. - useEffect: This hook runs after
useLayoutEffect
. It fires after the component render cycle has completed and after the screen has been updated. This behavior meansuseEffect
is best for tasks that do not require immediate, synchronous updates to the DOM, like API calls or setting up subscriptions. The console log insideuseEffect
will appear after the one fromuseLayoutEffect
.
While theoretically,
useEffect
might cause a flickering effect due to its asynchronous nature (executing after the browser has painted), in practice, observing a noticeable flicker can be difficult. Visually,useEffect
anduseLayoutEffect
often appear to behave similarly, especially for less complex DOM updates.
Practical Examples: useEffect and useLayoutEffect in Action 💫
To better grasp the nuances of useEffect
and useLayoutEffect
, let's dive into some practical examples. These will illustrate how each hook can be effectively utilized in different situations.
It's important to note that in many cases, especially in simple scenarios or with modern, high-performance browsers, these differences might not be visually apparent.
1️⃣ useEffect for Data Fetching🌐📈
Data fetching is a common use case for useEffect
. It allows you to request and load data from an API when your component is rendered.
Here’s a full example of a React component that uses useEffect
to fetch data from the JSONPlaceholder
API, a free fake online REST API:
import React, { useState, useEffect } from 'react';
const App = () => {
const [data, setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const jsonData = await response.json();
setData(jsonData);
} catch (error) {
console.error('Error fetching data: ', error);
}
};
fetchData();
}, []);
return (
<div>
<h1>Data Fetched from JSONPlaceholder API</h1>
<ul>
{data.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</div>
);
};
export default App;
The component renders a list of titles fetched from the API. The empty array in the dependency list of useEffect
ensures that the data fetching runs only once, similar to componentDidMount
in class components.
2️⃣ useLayoutEffect for DOM Manipulation: 📜
Let’s consider a situation where you want to adjust the scroll position of a list to the top immediately after some state changes. Doing this with useEffect
might result in a noticeable flicker, as the adjustment happens after the screen updates. useLayoutEffect
solves this by ensuring the adjustment is made before the screen paints.
Here’s an example:
import React, { useState, useLayoutEffect, useRef } from 'react';
const App = () => {
const [items, setItems] = useState([]);
const listRef = useRef(null);
const addItems = () => {
const newItems = [...Array(5).keys()].map(i => `Item ${i + items.length}`);
setItems([...items, ...newItems]);
};
useLayoutEffect(() => {
// Adjust the scroll position before the screen updates
if (listRef.current) {
listRef.current.scrollTop = 0;
}
}, [items]); // Dependency on 'items' state
return (
<div>
<button onClick={addItems}>Add Items</button>
<ul ref={listRef}>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
};
export default App;
In this component:
- We use
useState
to create anitems
state that stores a list of items. - A button is provided to add new items to the list.
- The
useLayoutEffect
hook is used to scroll the list to the top every time new items are added. This is done before the browser paints the updated UI, preventing any flicker or jump in the scroll position. - The
ref
attribute (listRef
) is used to reference the list DOM element for manipulating its scroll position.
This example showcases how useLayoutEffect
can be used to make smooth, flicker-free adjustments to the DOM in response to state changes in a React component.
Conclusion ✅
The choice between useEffect
and useLayoutEffect
often depends on the specific requirements of the DOM operation being performed. While the visual differences might not always be obvious, understanding the internal behavior of these hooks is key to optimizing your React application's performance and ensuring a smooth user experience.
useEffect
is your go-to hook for most side effects, especially those that don't require immediate interaction with the DOM, like data fetching or setting up subscriptions. Its ability to react to state and prop changes makes it incredibly versatile for a wide range of use cases.
On the other hand, useLayoutEffect
is essential when you need to make synchronous updates in direct response to DOM changes. It's the perfect tool for avoiding visual glitches and ensuring a smooth user experience when manipulating the DOM.
下载开源日报APP:https://openingsource.org/2579/
加入我们:https://openingsource.org/about/join/
关注我们:https://openingsource.org/about/love/