」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 開發人員在 React 中使用 useState 時犯的常見錯誤(以及如何修復它們)

開發人員在 React 中使用 useState 時犯的常見錯誤(以及如何修復它們)

發佈於2024-11-03
瀏覽:713

Common Mistakes Developers Make with useState in React (And How to Fix Them)

React 的 useState 钩子是管理功能组件中状态的重要工具,但很容易陷入一些常见的陷阱。无论您是刚刚开始使用 React 还是已经使用它一段时间了,避免这些错误都可以帮助您避免意外的错误和性能问题。

让我们来看看 10 个常见错误以及如何避免它们以编写更简洁、更高效的代码。

1. 初始状态类型错误

当初始状态类型与状态更新期间预期的类型不匹配时,会出现最常见的问题之一。

❌错误:初始状态类型不匹配

const [count, setCount] = useState(0);
setCount("1"); // Error: Argument of type 'string' is not assignable to parameter of type 'number'.

✅ 解决方案:使用 TypeScript 或显式指定类型。

const [count, setCount] = useState(0);
setCount(1); // No issues now.

2.不使用功能更新

根据先前的值更新状态时,直接引用当前状态可能会导致值过时,尤其是在异步操作中。

❌错误:直接使用当前状态

setCount(count   1); // Can cause bugs in async scenarios.

✅解决方案:使用函数形式进行安全更新。

setCount((prevCount) => prevCount   1); // Ensures you always have the latest value.

3. 存储派生状态

避免将值存储在可以从其他状态或道具派生的状态中。这可能会导致不必要的重新渲染和同步问题。

❌ 错误:存储派生状态

const [count, setCount] = useState(0);
const [doubleCount, setDoubleCount] = useState(count * 2);

✅ 解决方案:在渲染期间导出值而不是使用状态。

const [count, setCount] = useState(0);
const doubleCount = count * 2; // No need to store this in state.

4. 渲染阶段内的状态更新

在渲染阶段调用 setState 会导致无限循环和性能问题。

❌错误:在渲染期间设置状态

const [count, setCount] = useState(0);
setCount(1); // Infinite loop!

✅解决方案:在事件处理程序或效果中触发状态变化。

const handleClick = () => setCount(1);

5. 直接改变状态

如果直接改变状态,React 将不会检测到更改,尤其是对于数组或对象。

❌错误:直接改变状态

const [items, setItems] = useState([1, 2, 3]);
items.push(4); // Mutation happens here, React won’t re-render!

✅解决方案:返回一个新的数组或对象来触发重新渲染。

setItems((prevItems) => [...prevItems, 4]); // Spread to create a new array.

6. 复杂状态的未定义或不正确的类型

处理复杂状态时,未定义正确的类型可能会导致运行时问题和混乱。

❌错误:隐式类型可能导致错误

const [user, setUser] = useState({ name: "", age: 0 });
setUser({ name: "John", age: "thirty" }); // Type error: Age should be a number.

✅解决方案:用正确的类型定义状态的形状。

type User = { name: string; age: number };
const [user, setUser] = useState({ name: "", age: 0 });

7. 将状态用于可变值(如计时器)

对不影响渲染的值(例如计时器)使用 useState 会导致不必要的重新渲染。

❌ 错误:使用状态来表示可变值

const [timerId, setTimerId] = useState(null);

✅ 解决方案:对不需要重新渲染的可变值使用 useRef。

const timerIdRef = useRef(null);

8. 没有正确合并状态对象

与类组件不同,useState 不会自动合并更新。忘记这一点可能会导致覆盖您的部分状态。

❌错误:覆盖状态而不是合并

const [user, setUser] = useState({ name: '', age: 0 });
setUser({ age: 25 }); // The 'name' field is now lost!

✅ 解决方案:使用展开运算符合并状态更新。

setUser((prevUser) => ({ ...prevUser, age: 25 })); // Merges with existing state.

9. 使用状态进行高频更新

跟踪状态中的窗口尺寸等高频值可能会因过度重新渲染而导致性能问题。

❌错误:使用状态进行频繁更新

const [size, setSize] = useState(window.innerWidth);
window.addEventListener("resize", () => setSize(window.innerWidth));

✅解决方案:使用useRef或debounce来减少性能损失。

const sizeRef = useRef(window.innerWidth);
useEffect(() => {
  const handleResize = () => {
    sizeRef.current = window.innerWidth;
  };
  window.addEventListener("resize", handleResize);
  return () => window.removeEventListener("resize", handleResize);
}, []);

10. 假设状态更新是同步的

React 状态更新是异步的,但许多开发人员错误地认为更改会立即应用。

❌错误:假设状态更改是立即的

setCount(count   1);
console.log(count); // Logs the old value, not the updated one!

✅解决方案:使用useEffect跟踪状态变化并确保使用最新的值。

useEffect(() => {
  console.log(count); // Logs the updated value after re-render.
}, [count]);

最后的想法?

避免这些 useState 陷阱将使您的 React 代码更加健壮、可读和高性能。了解 React 的状态机制如何工作并了解最佳实践将节省您的调试时间并增强您的整体开发体验。

您有什么 useState 技巧或错误可以分享吗?将它们放在下面的评论中! ?

版本聲明 本文轉載於:https://dev.to/ujjwalkar21/common-mistakes-developers-make-with-usestate-in-react-and-how-to-fix-them-1cmi?1如有侵犯,請聯絡study_golang @163.com刪除
最新教學 更多>
  • 如何將來自三個MySQL表的數據組合到新表中?
    如何將來自三個MySQL表的數據組合到新表中?
    mysql:從三個表和列的新表創建新表 答案:為了實現這一目標,您可以利用一個3-way Join。 選擇p。 *,d.content作為年齡 來自人為p的人 加入d.person_id = p.id上的d的詳細信息 加入T.Id = d.detail_id的分類法 其中t.taxonomy ...
    程式設計 發佈於2025-07-05
  • Python元類工作原理及類創建與定制
    Python元類工作原理及類創建與定制
    python中的metaclasses是什麼? Metaclasses負責在Python中創建類對象。就像類創建實例一樣,元類也創建類。他們提供了對類創建過程的控制層,允許自定義類行為和屬性。 在Python中理解類作為對象的概念,類是描述用於創建新實例或對象的藍圖的對象。這意味著類本身是使用...
    程式設計 發佈於2025-07-05
  • Python中嵌套函數與閉包的區別是什麼
    Python中嵌套函數與閉包的區別是什麼
    嵌套函數與python 在python中的嵌套函數不被考慮閉合,因為它們不符合以下要求:不訪問局部範圍scliables to incling scliables在封裝範圍外執行範圍的局部範圍。 make_printer(msg): DEF打印機(): 打印(味精) ...
    程式設計 發佈於2025-07-05
  • Java中假喚醒真的會發生嗎?
    Java中假喚醒真的會發生嗎?
    在Java中的浪費喚醒:真實性或神話? 在Java同步中偽裝喚醒的概念已經是討論的主題。儘管存在這種行為的潛力,但問題仍然存在:它們實際上是在實踐中發生的嗎? Linux的喚醒機制根據Wikipedia關於偽造喚醒的文章,linux實現了pthread_cond_wait()功能的Linux實現,...
    程式設計 發佈於2025-07-05
  • 在程序退出之前,我需要在C ++中明確刪除堆的堆分配嗎?
    在程序退出之前,我需要在C ++中明確刪除堆的堆分配嗎?
    在C中的顯式刪除 在C中的動態內存分配時,開發人員通常會想知道是否有必要在heap-procal extrable exit exit上進行手動調用“ delete”操作員,但開發人員通常會想知道是否需要手動調用“ delete”操作員。本文深入研究了這個主題。 在C主函數中,使用了動態分配變量(...
    程式設計 發佈於2025-07-05
  • 如何使用node-mysql在單個查詢中執行多個SQL語句?
    如何使用node-mysql在單個查詢中執行多個SQL語句?
    Multi-Statement Query Support in Node-MySQLIn Node.js, the question arises when executing multiple SQL statements in a single query using the node-mys...
    程式設計 發佈於2025-07-05
  • 如何在Java字符串中有效替換多個子字符串?
    如何在Java字符串中有效替換多個子字符串?
    在java 中有效地替換多個substring,需要在需要替換一個字符串中的多個substring的情況下,很容易求助於重複應用字符串的刺激力量。 However, this can be inefficient for large strings or when working with nu...
    程式設計 發佈於2025-07-05
  • 哪種方法更有效地用於點 - 填點檢測:射線跟踪或matplotlib \的路徑contains_points?
    哪種方法更有效地用於點 - 填點檢測:射線跟踪或matplotlib \的路徑contains_points?
    在Python Matplotlib's path.contains_points FunctionMatplotlib's path.contains_points function employs a path object to represent the polygon.它...
    程式設計 發佈於2025-07-05
  • 在Python中如何創建動態變量?
    在Python中如何創建動態變量?
    在Python 中,動態創建變量的功能可以是一種強大的工具,尤其是在使用複雜的數據結構或算法時,Dynamic Variable Creation的動態變量創建。 Python提供了幾種創造性的方法來實現這一目標。 利用dictionaries 一種有效的方法是利用字典。字典允許您動態創建密鑰並...
    程式設計 發佈於2025-07-05
  • Go web應用何時關閉數據庫連接?
    Go web應用何時關閉數據庫連接?
    在GO Web Applications中管理數據庫連接很少,考慮以下簡化的web應用程序代碼:出現的問題:何時應在DB連接上調用Close()方法? ,該特定方案將自動關閉程序時,該程序將在EXITS EXITS EXITS出現時自動關閉。但是,其他考慮因素可能保證手動處理。 選項1:隱式關閉終...
    程式設計 發佈於2025-07-05
  • 如何將MySQL數據庫添加到Visual Studio 2012中的數據源對話框中?
    如何將MySQL數據庫添加到Visual Studio 2012中的數據源對話框中?
    在Visual Studio 2012 儘管已安裝了MySQL Connector v.6.5.4,但無法將MySQL數據庫添加到實體框架的“ DataSource對話框”中。為了解決這一問題,至關重要的是要了解MySQL連接器v.6.5.5及以後的6.6.x版本將提供MySQL的官方Visual...
    程式設計 發佈於2025-07-05
  • Java是否允許多種返回類型:仔細研究通用方法?
    Java是否允許多種返回類型:仔細研究通用方法?
    在Java中的多個返回類型:一種誤解類型:在Java編程中揭示,在Java編程中,Peculiar方法簽名可能會出現,可能會出現,使開發人員陷入困境,使開發人員陷入困境。 getResult(string s); ,其中foo是自定義類。該方法聲明似乎擁有兩種返回類型:列表和E。但這確實是如此嗎...
    程式設計 發佈於2025-07-05
  • 如何使用Regex在PHP中有效地提取括號內的文本
    如何使用Regex在PHP中有效地提取括號內的文本
    php:在括號內提取文本在處理括號內的文本時,找到最有效的解決方案是必不可少的。一種方法是利用PHP的字符串操作函數,如下所示: 作為替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式來搜索特...
    程式設計 發佈於2025-07-05
  • 如何使用不同數量列的聯合數據庫表?
    如何使用不同數量列的聯合數據庫表?
    合併列數不同的表 當嘗試合併列數不同的數據庫表時,可能會遇到挑戰。一種直接的方法是在列數較少的表中,為缺失的列追加空值。 例如,考慮兩個表,表 A 和表 B,其中表 A 的列數多於表 B。為了合併這些表,同時處理表 B 中缺失的列,請按照以下步驟操作: 確定表 B 中缺失的列,並將它們添加到表的...
    程式設計 發佈於2025-07-05
  • \“(1)vs.(;;):編譯器優化是否消除了性能差異?\”
    \“(1)vs.(;;):編譯器優化是否消除了性能差異?\”
    答案: 在大多數現代編譯器中,while(1)和(1)和(;;)之間沒有性能差異。編譯器: perl: 1 輸入 - > 2 2 NextState(Main 2 -E:1)V-> 3 9 Leaveloop VK/2-> A 3 toterloop(next-> 8 last-> 9 ...
    程式設計 發佈於2025-07-05

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3