搜尋
首頁web前端js教程停止犯這些組件錯誤

停止犯這些組件錯誤

Nov 19, 2024 am 10:43 AM

Stop Making These Component Mistakes

事實是,組件看似簡單。上手很簡單——定義一個函數,回傳一些 JSX,然後就到此為止。但是要編寫乾淨、可維護且易於使用的元件嗎?這是一場完全不同的比賽。

在沒有意識到的情況下,我們建立了以下元件:

  • 太大了,一眼看不懂。
  • 測試起來非常困難。
  • 耦合如此緊密,無法重複使用。
  • 由於糟糕的績效決策而遲緩。

在這篇文章中,我將引導您了解開發人員在使用 React 元件時最常見的錯誤。更重要的是,我將向您展示如何在不破壞整個應用程式的情況下修復它們。

無論您是剛入門還是擁有多年的經驗,這些技巧都將幫助您編寫出不僅具有功能性而且易於維護的組件。

“一切組件”反模式

讓我們來談談我們都犯過的經典錯誤:一切組件。您已經看到它了——它一開始很小而且天真無邪,可能是一個簡單的表單或儀表板。快轉一點,現在它正在管理狀態、處理 API 呼叫、格式化數據,還可能為您沖泡早晨咖啡。

// Please, no more of this
const UserDashboard = () => {
  const [userData, setUserData] = useState(null);
  const [orders, setOrders] = useState([]);
  const [notifications, setNotifications] = useState([]);
  const [settings, setSettings] = useState({});
  const [isEditing, setIsEditing] = useState(false);
  const [activeTab, setActiveTab] = useState('profile');

  // 15 separate useEffects
  // 10 different event handlers
  // Multiple conditional renders
  // 300+ lines of chaos
};

聽起來很熟悉嗎?

如何判斷你是否有罪

如果出現以下情況,您的組件可能已變成「一切組件」:

  • 狀態過載:您正在追蹤超過 3-4 個獨立的狀態。
  • 無休止的滾動:你花了太多時間尋找特定的功能或邏輯。
  • 依賴項膨脹: 你的 useEffect 依賴項看起來就像你的每週購物清單。
  • 否認功能蔓延:你不斷告訴自己,多一個功能不會有什麼壞處。

分解它

解決方案?不要使用單一的所有組件,而是將職責分解為更小的、更有針對性的部分。

// A cleaner, smarter approach
const UserDashboard = () => {
  return (
    <div>
      <userprofile></userprofile>
      <orderhistory></orderhistory>
      <notificationcenter></notificationcenter>
      <usersettings></usersettings>
    </div>
  );
};

關鍵原則:邏輯>佈局

重構時,不要根據組件在螢幕上的外觀來破壞它們。按責任劃分他們。問問自己:這個功能是否值得擁有自己的組件?如果它正在處理一些不同的東西——例如用戶個人資料或訂單歷史記錄——它可能會這樣做。

提示: 一個好的組件只做一件事並且做得很好。如果您很難用一句話描述它的目的,那麼它很可能試圖做太多事情。

螺旋槳鑽井地獄

我們來討論一下不太好玩的「傳遞道具」遊戲。如果您曾經將同一個 prop 透過多個元件傳遞給一個深度嵌套的子元件,那麼您就陷入了 prop 鑽探地獄。

// Please, no more of this
const UserDashboard = () => {
  const [userData, setUserData] = useState(null);
  const [orders, setOrders] = useState([]);
  const [notifications, setNotifications] = useState([]);
  const [settings, setSettings] = useState({});
  const [isEditing, setIsEditing] = useState(false);
  const [activeTab, setActiveTab] = useState('profile');

  // 15 separate useEffects
  // 10 different event handlers
  // Multiple conditional renders
  // 300+ lines of chaos
};

這種方法不僅令人煩惱,而且還會造成長期問題。想像一下需要重命名 user 屬性。突然,您在五個或更多地方更新它。更糟的是,您最終將組件與它們甚至不使用的資料綁定在一起。

如何解決這個問題

無需用道具來應付燙手山芋。這裡有兩個實用的解決方案,可以完全避免鑽孔。

1。使用共享資料的上下文

如果跨應用程式的不同部分存取一段數據,React 的 Context API 可以簡化事情。

// A cleaner, smarter approach
const UserDashboard = () => {
  return (
    <div>
      <userprofile></userprofile>
      <orderhistory></orderhistory>
      <notificationcenter></notificationcenter>
      <usersettings></usersettings>
    </div>
  );
};

2。使用組合來提高靈活性

不要通過層強制道具,而是重組組件,以便它們只傳遞需要的內容。

// This is exhausting
const App = () => {
  const [user, setUser] = useState({});
  return (
    <layout user="{user}">
      <sidebar user="{user}">
        <navigation user="{user}">
          <usermenu user="{user}"></usermenu>
        </navigation>
      </sidebar>
    </layout>
  );
};

重點

上下文非常適合應用程式範圍的數據,例如使用者資訊、主題或全域設定。然而,它並不總是最好的選擇——不要過度使用它。對於局部狀態,考慮是否可以調整組件結構以避免完全鑽取。

目標是讓你的元件清晰且可維護。避免螺旋鑽探將為您節省時間、減少挫敗感並避免日後無數令人頭痛的問題。

過早的優化陷阱

您可能聽過關於過早優化是萬惡之源的名言。好吧,歡迎來到組件級邪惡。我說的是那些時候,我們甚至不知道是否需要兩次之前就嘗試讓所有東西都可重複使用。

通常是這樣的:

const UserContext = createContext();

const App = () => {
  const [user, setUser] = useState({});
  return (
    <usercontext.provider value="{user}">
      <layout>
        <sidebar>
          <navigation></navigation>
        </sidebar>
      </layout>
    </usercontext.provider>
  );
};

// Use it only where needed
const UserMenu = () => {
  const user = useContext(UserContext);
  return <div>{user.name}</div>;
};

讓你的組件自然發展。為您知道您今天需要的東西而建造。如果出現新的需求,請在可以清楚證明其合理性的情況下添加功能。過早的優化會浪費時間,增加複雜性,而且很少有回報。

記住: YAGNI 原則(你不會需要它)也適用於組件。當你真正遇到了他們正在解決的問題時,最好的抽象就會出現。過度設計可能會讓人覺得很主動,但簡單總是勝出。

副作用管理不善

這是一個不良效果管理的經典例子。看起來很眼熟嗎?

// Focused components for better clarity
const Navigation = ({ children }) => {
  return <nav>{children}</nav>;
};

// Pass data only where required
const App = () => {
  const user = useUser();
  return (
    <layout>
      <navigation>
        <usermenu user="{user}"></usermenu>
      </navigation>
    </layout>
  );
};

常見錯誤和修復

1) 混亂的資料取得

糟糕的資料處理產生的錯誤比它解決的錯誤還要多。這是一種更簡潔的方法:

// Behold, the over-engineered button
const Button = ({ 
  children,
  variant = 'primary',
  size = 'medium',
  isFullWidth = false,
  isDisabled = false,
  isLoading = false,
  leftIcon,
  rightIcon,
  onClick,
  customClassName,
  style,
  loadingText = 'Loading...',
  tooltipText,
  animationType,
  // ... 10 more props
}) => {
  // 50 lines of prop processing logic
  return (
    <button classname="{generateComplexClassNames()}">



<h3>
  
  
  Why This Hurts
</h3>

<ul>
<li>Your “simple” button now requires an instruction manual.</li>
<li>Most of those 15+ props will never be used.</li>
<li>Making updates becomes risky because you have to account for endless combinations.</li>
<li>Writing tests becomes painful, with a hundred possible scenarios to consider.</li>
</ul>

<h3>
  
  
  Better Approach:
</h3>

<p>Instead of building for every imaginable scenario, start small and let your components grow as needed.<br>
</p>

<pre class="brush:php;toolbar:false">// Start simple
const Button = ({ children, onClick, variant = 'primary' }) => {
  return (
    <button classname="{`btn" btn- onclick="{onClick}">
      {children}
    </button>
  );
}

// Create specific buttons when you actually need them
const LoadingButton = ({ isLoading, children, ...props }) => {
  return (
    <button>
      {isLoading ? 'Loading...' : children}
    </button>
  );
}

2) 忘記清理

總是清理乾淨自己:

const UserProfile = ({ userId }) => {  
  const [user, setUser] = useState(null);  
  const [posts, setPosts] = useState([]);  

  // Dependency array woes
  useEffect(() => {  
    fetchUserData(userId);  
    fetchUserPosts(userId);  
    // No cleanup? Yikes.
  }, []); // eslint-disable-line react-hooks/exhaustive-deps  

  // Multiple effects, all tangled
  useEffect(() => {  
    const subscription = subscribeToUserStatus(userId);  
  }, [userId]);  

  // Cleanup? What cleanup?
  useEffect(() => {  
    const interval = setInterval(checkNotifications, 5000);  
  }, []);  
};

3) 忽略競爭條件

使用此技術避免重疊請求:

// Improved version
const UserProfile = ({ userId }) => {  
  const { data: user, isLoading } = useQuery(  
    ['user', userId],  
    () => fetchUserData(userId)  
  );  

  // Keep concerns separate
  const { data: posts } = useQuery(  
    ['posts', userId],  
    () => fetchUserPosts(userId),  
    { enabled: !!user }  
  );  
};

快速提示

  • 使用 useEffect 之前請三思:有時候,你可能根本不需要它。
  • 保持專注:一種效果應該承擔一種責任。
  • 始終清理:訂閱、間隔和事件監聽器需要注意。
  • 使用正確的工具:像 React Query 這樣的函式庫可以簡化資料取得和快取。
  • 不要用 eslint-disable 作弊:修復依賴問題而不是隱藏它們。

性能盲點

讓我們來談談那些偷偷摸摸的效能問題。他們是那種在雷達下飛行的人,因為一切看起來都很好——直到事實並非如此。讓我們揭開這些無聲的罪魁禍首,看看如何解決它們。

問題

這是一個存在一些微妙性能缺陷的組件:

// Please, no more of this
const UserDashboard = () => {
  const [userData, setUserData] = useState(null);
  const [orders, setOrders] = useState([]);
  const [notifications, setNotifications] = useState([]);
  const [settings, setSettings] = useState({});
  const [isEditing, setIsEditing] = useState(false);
  const [activeTab, setActiveTab] = useState('profile');

  // 15 separate useEffects
  // 10 different event handlers
  // Multiple conditional renders
  // 300+ lines of chaos
};

你能發現問題嗎?讓我們把它們分解一下。

修補

1) 記住昂貴的計算

不要在每次渲染時重新計算所有內容,而是使用 useMemo 來快取結果:

// A cleaner, smarter approach
const UserDashboard = () => {
  return (
    <div>
      <userprofile></userprofile>
      <orderhistory></orderhistory>
      <notificationcenter></notificationcenter>
      <usersettings></usersettings>
    </div>
  );
};

這避免了在每次渲染時重新計算資料並重新建立事件處理程序。它還可以防止帶有備忘錄的子元件不必要的重新渲染。

2) 高效率的狀態更新

糟糕的狀態管理也會降低效能。這是處理搜尋結果等更新的更好方法:

// This is exhausting
const App = () => {
  const [user, setUser] = useState({});
  return (
    <layout user="{user}">
      <sidebar user="{user}">
        <navigation user="{user}">
          <usermenu user="{user}"></usermenu>
        </navigation>
      </sidebar>
    </layout>
  );
};

去抖動確保我們不會在每次按鍵時獲取數據,從而減少不必要的 API 呼叫和重新渲染。

快速效能提示

  • 不要過度使用記憶:僅在值得的時候進行最佳化。
  • 避免內嵌函數:穩定的引用可以提高效能。
  • 保持 props 可預測:淺且穩定的 props 有助於組件保持高效。
  • 分解大型清單:像react-window這樣的工具可以優雅地處理大資料集。
  • 將狀態移得更近:僅在實際需要的地方管理狀態。
  • 使用 DevTools 進行分析:最佳化前始終進行測量。

結論

建構元件並不是什麼複雜的事情,但說實話,我們很容易養成壞習慣。我犯過這些錯誤中的每一個(有時仍然會犯)。沒關係。重要的是儘早發現它們、修復它們並避免粗糙的程式碼庫。

更好組件的快速清單

✅ 單一職責:如果您無法用一句話概括組件的工作,那麼就該將其分解。

✅ 道具管理:層層傳遞道具?考慮使用上下文或利用組合來代替。

✅ 狀態與效果:集中效果,正確清理它們,並讓現代工具處理複雜的資料擷取。

✅ 效能:不要為了最佳化而最佳化-首先要衡量。在需要時巧妙地使用 memo、useMemo 和 useCallback 等工具。

✅ 從簡單開始:解決你現在遇到的問題,而不是將來可能遇到的問題。

最好的組件不是華而不實或過於聰明 - 它們是您的團隊可以在六個月內閱讀和維護的組件。

記住:這些不是硬性規則,只是指導方針。有時你會打破它們,那很好。我們的目標不是完美,而是建立一些組件,讓您在以後重新審視自己的職業選擇時不會產生疑問。

以上是停止犯這些組件錯誤的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

了解JavaScript引擎:實施詳細信息了解JavaScript引擎:實施詳細信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python vs. JavaScript:學習曲線和易用性Python vs. JavaScript:學習曲線和易用性Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python vs. JavaScript:社區,圖書館和資源Python vs. JavaScript:社區,圖書館和資源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C到JavaScript:所有工作方式從C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版