第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機(jī)立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

關(guān)于此 React 自定義鉤子用法的困惑

關(guān)于此 React 自定義鉤子用法的困惑

交互式愛情 2022-09-16 22:03:47
我正在看一些關(guān)于 React Hooks 的教程,在教程中,作者創(chuàng)建了一個用于呈現(xiàn)可重用下拉列表的鉤子。代碼是這樣的useDropdownimport React, { useState } from "react";const useDropdown = (label, defaultState, options) => {  const [state, updateState] = useState(defaultState);  const id = `use-dropdown-${label.replace(" ", "").toLowerCase()}`;  const Dropdown = () => (    <label htmlFor={id}>      {label}      <select        id={id}        value={state}        onChange={e => updateState(e.target.value)}        onBlur={e => updateState(e.target.value)}        disabled={!options.length}      >        <option />        {options.map(item => (          <option key={item} value={item}>            {item}          </option>        ))}      </select>    </label>  );  return [state, Dropdown, updateState];};export default useDropdown;他在這樣的組件中使用了這個import React, { useState, useEffect } from "react";import useDropdown from "./useDropdown";const SomeComponent = () => {  const [animal, AnimalDropdown] = useDropdown("Animal", "dog", ANIMALS);  const [breed, BreedDropdown, updateBreed] = useDropdown("Breed", "", breeds);  return (    <div className="search-params">      <form>        <label htmlFor="location">          Location          <input            id="location"            value={location}            placeholder="Location"            onChange={e => updateLocation(e.target.value)}          />        </label>        <AnimalDropdown />        <BreedDropdown />        <button>Submit</button>      </form>    </div>  );};export default SomeComponent;他說,通過這種方式,我們可以創(chuàng)建可重用的下拉組件。我想知道這與定義一個普通的舊Drampdown組件并將道具傳遞到其中有何不同。在這種情況下,我能想到的唯一區(qū)別是,現(xiàn)在我們能夠在父組件(即)中獲取狀態(tài)和setState,并直接從那里讀取/設(shè)置子組件的狀態(tài)(即組件輸出)。然而,這是否被認(rèn)為是一種反模式,因?yàn)槲覀冋谄茐膯蜗驍?shù)據(jù)流?SomeComponentuseDropdown
查看完整描述

3 回答

?
慕萊塢森

TA貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超4個贊

雖然對于如何定義自定義鉤子以及應(yīng)該包含什么邏輯沒有硬核限制,但它是一種反模式,可以編寫返回JSX的鉤子。

您應(yīng)該評估每種方法給您帶來的好處,然后決定特定的代碼段

使用鉤子返回JSX有一些缺點(diǎn)

  • 當(dāng)您編寫返回 JSX 組件的鉤子時,您實(shí)際上是在功能組件中定義組件,因此每次重新渲染時,您都將創(chuàng)建該組件的新實(shí)例。這將導(dǎo)致組件被卸載并再次安裝。這對性能不利,如果您在組件中有狀態(tài)登錄,也會有缺陷,因?yàn)闋顟B(tài)將隨著父級的每次重新渲染而重置

  • 通過在鉤子中定義 JSX 組件,您可以根據(jù)需要取消延遲加載組件的選項(xiàng)。

  • 對組件的任何性能優(yōu)化都需要您使用,而這些優(yōu)化并不能為您提供自定義比較器功能(如 React.memo)的靈活性useMemo

另一方面的好處是,您可以控制父級組件的狀態(tài)。但是,您仍然可以通過使用受控組件方法實(shí)現(xiàn)相同的邏輯

import React, { useState } from "react";


const Dropdown = Reat.memo((props) => {

  const { label, value, updateState, options } = props;

  const id = `use-dropdown-${label.replace(" ", "").toLowerCase()}`;

  return (

    <label htmlFor={id}>

      {label}

      <select

        id={id}

        value={value}

        onChange={e => updateState(e.target.value)}

        onBlur={e => updateState(e.target.value)}

        disabled={!options.length}

      >

        <option />

        {options.map(item => (

          <option key={item} value={item}>

            {item}

          </option>

        ))}

      </select>

    </label>

  );

});


export default Dropdown;

并將其用作


import React, { useState, useEffect } from "react";

import useDropdown from "./useDropdown";


const SomeComponent = () => {

  const [animal, updateAnimal] = useState("dog");

  const [breed, updateBreed] = useState("");


  return (

    <div className="search-params">

      <form>

        <label htmlFor="location">

          Location

          <input

            id="location"

            value={location}

            placeholder="Location"

            onChange={e => updateLocation(e.target.value)}

          />

        </label>

        <Dropdown label="animal" value={animal} updateState={updateAnimal} options={ANIMALS}/>

        <Dropdown label="breed" value={breed} updateState={updateBreed} options={breeds}/>

        <button>Submit</button>

      </form>

    </div>

  );

};


export default SomeComponent;


查看完整回答
反對 回復(fù) 2022-09-16
?
瀟湘沐

TA貢獻(xiàn)1816條經(jīng)驗(yàn) 獲得超6個贊

反模式是一個直言不諱的短語,用于描述其他開發(fā)人員不同意的簡單或復(fù)雜的解決方案。我同意德魯?shù)挠^點(diǎn),即鉤子打破了傳統(tǒng)的設(shè)計(jì),做了比它應(yīng)該做的更多的事情。

根據(jù) React 的鉤子文檔,鉤子的目的是允許你使用狀態(tài)和其他 React 特性,而無需編寫類。這通常被認(rèn)為是設(shè)置狀態(tài),執(zhí)行計(jì)算任務(wù),在異步事務(wù)中執(zhí)行API或其他查詢,以及響應(yīng)用戶輸入。理想情況下,功能組件應(yīng)該可以與類組件互換,但實(shí)際上,這要困難得多。

用于創(chuàng)建下拉列表組件的特定解決方案雖然有效,但并不是一個好的解決方案。為什么?這是令人困惑的,它不是不言自明的,很難理解發(fā)生了什么。使用鉤子,它們應(yīng)該很簡單并執(zhí)行單個任務(wù),例如按鈕回調(diào)處理程序,計(jì)算并返回記憶結(jié)果,或執(zhí)行通常委派給的其他一些任務(wù)。this.doSomething()

返回 JSX 的鉤子根本不是真正的鉤子,它們只是功能組件,即使它們對鉤子使用正確的前綴命名約定。

在 React 和組件更新的單向通信方面也存在混亂。對數(shù)據(jù)可以通過哪種方式?jīng)]有限制,并且可以以與Angular類似的方式進(jìn)行處理。有一些庫允許您訂閱和發(fā)布對共享類屬性的更改,這些庫將更新偵聽的任何 UI 組件,并且該組件也可以更新它。您還可以使用 RxJS 隨時進(jìn)行異步更改,從而更新 UI。mobx

具體示例確實(shí)避開了 SOLID 原則,為父組件提供輸入點(diǎn)來控制子組件的數(shù)據(jù)。這是典型的強(qiáng)類型語言,如Java,其中進(jìn)行異步通信更加困難(現(xiàn)在不是真正的問題,但曾經(jīng)是)。父組件沒有理由不能更新子組件 - 這是 React 的基本組成部分。添加的抽象越多,添加的復(fù)雜性就越高,故障點(diǎn)就越多。

添加異步函數(shù)、可觀察量 (mobx/rxjs) 或上下文的使用可以減少直接數(shù)據(jù)耦合,但它將創(chuàng)建更復(fù)雜的解決方案。


查看完整回答
反對 回復(fù) 2022-09-16
?
翻閱古今

TA貢獻(xiàn)1780條經(jīng)驗(yàn) 獲得超5個贊

我同意 Drew 的觀點(diǎn),即使用自定義鉤子僅返回基于函數(shù)參數(shù)的 jsx 會破壞傳統(tǒng)的組件抽象。為了擴(kuò)展這一點(diǎn),我可以想出四種不同的方法來使用 React 中的 jsx。


靜態(tài) JSX


如果jsx不依賴于狀態(tài)/道具,你可以把它定義為一個甚至在你的組件之外。如果您有一系列內(nèi)容,這尤其有用。const


例:


const myPs = 

[

 <p key="who">My name is...</p>,

 <p key="what">I am currently working as a...</p>,

 <p key="where">I moved to ...</p>,

];


const Component = () => (

  <>

   { myPs.map(p => p) }

  </>

);

元件


對于 jsx 的有狀態(tài)和無狀態(tài)部分。組件是將 UI 分解為可維護(hù)和可重用部分的 React 方式。


上下文


上下文提供程序返回 jsx(因?yàn)樗鼈円彩恰爸皇恰苯M件)。通常,您只需將子組件包裝在要提供的上下文中,如下所示:


  return (

    <UserContext.Provider value={context}>

      {children}

    </UserContext.Provider>

  );

但上下文也可用于開發(fā)全局組件。想象一個維護(hù)全局模式對話的對話上下文。目標(biāo)是永遠(yuǎn)不要一次打開多個模式對話框。您可以使用上下文來管理對話框的狀態(tài),但也可以通過上下文提供程序組件呈現(xiàn)全局對話框 jsx:


function DialogProvider({ children }) {

  const [showDialog, setShowDialog] = useState(false);

  const [dialog, setDialog] = useState(null);


  const openDialog = useCallback((newDialog) => {

    setDialog(newDialog);

    setShowDialog(true);

  }, []);


  const closeDialog = useCallback(() => {

    setShowDialog(false);

    setDialog(null);

  }, []);


  const context = {

    isOpen: showDialog,

    openDialog,

    closeDialog,

  };


  return (

    <DialogContext.Provider value={context}>

      { showDialog && <Dialog>{dialog}</Dialog> }

      {children}

    </DialogContext.Provider>

  );

}

更新上下文還將為用戶更新 UI 中的全局對話框。設(shè)置新對話框?qū)h除舊對話框。


定制掛鉤


通常,鉤子是封裝要在組件之間共享的邏輯的好方法。我看到它們被用作復(fù)雜上下文的抽象層。想象一下,一個非常復(fù)雜,你的大多數(shù)組件只關(guān)心用戶是否登錄,你可以通過自定義鉤子將其抽象出來。UserContextuseIsLoggedIn


const useIsLoggedIn = () => {

  const { user } = useContext(UserContext);

  const [isLoggedIn, setIsLoggedIn] = useState(!!user);


  useEffect(() => {

    setIsLoggedIn(!!user);

  }, [user]);

  return isLoggedIn;

};

另一個很好的例子是一個鉤子,它結(jié)合了你實(shí)際上想要在不同組件/容器中重用(而不是共享)的狀態(tài):


const useStatus = () => {

  const [status, setStatus] = useState(LOADING_STATUS.IS_IDLE);

  const [isLoading, setIsLoading] = useState(false);


  useEffect(() => {

    setIsLoading(status === LOADING_STATUS.IS_LOADING);

  }, [status]);


  return { status, setStatus, isLoading };

};

此掛鉤創(chuàng)建 API 調(diào)用相關(guān)狀態(tài),您可以在處理 API 調(diào)用的任何組件中重用該狀態(tài)。


我舉了一個例子,我實(shí)際上使用自定義鉤子來渲染jsx,而不是使用組件:


const useGatsbyImage = (src, alt) => {

  const { data } = useContext(ImagesContext);

  const fluid = useMemo(() => (

    data.allFile.nodes.find(({ relativePath }) => src === relativePath).childImageSharp.fluid

  ), [data, src]);


  return (

    <Img

      fluid={fluid}

      alt={alt}

    />

  );

};

我可以為此創(chuàng)建一個組件嗎?當(dāng)然,但我也只是抽象出一個上下文,對我來說,這是一個使用鉤子的模式。反應(yīng)不是固執(zhí)己見的。您可以定義自己的約定。


再一次,我認(rèn)為德魯已經(jīng)給了你一個很好的答案。我希望我的例子能幫助你更好地了解 React 為你提供的不同工具的用法。


查看完整回答
反對 回復(fù) 2022-09-16
  • 3 回答
  • 0 關(guān)注
  • 167 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號