開源日報每天推薦一個 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/