最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React奇奇怪怪技巧之內(nèi)聯(lián)hook

 更新時(shí)間:2026年03月30日 08:38:36   作者:fe小陳  
Hooks是React提供的特殊函數(shù),專門用于函數(shù)組件,讓你無需編寫類組件,就能使用 React 的核心特性(狀態(tài)、副作用、上下文、緩存等),這篇文章主要介紹了React奇奇怪怪技巧之內(nèi)聯(lián)hook的相關(guān)資料,需要的朋友可以參考下

本文介紹一種 react 當(dāng)中在一堆 jsx 中嵌入 hook 的方式 inlineHook。

場景 or 為什么

一、列表渲染

列表渲染中,你或許需要為每個(gè)元素準(zhǔn)備其狀態(tài)和副作用,這時(shí)候你就需要用一個(gè)新的組件,如果需要用到父組件的狀態(tài),還需要透傳一堆 props 給它。也就是說,你為了使用一個(gè)組件,需要包一個(gè)新的組件出來。

function Parent(){
    // states
    // effects 
    return <>
        {list.map(item =>
            <ChildComponentWrap
                key={item.key} 
               // ...state
               // ...callback
               // 這里其實(shí)可能很多
            />
        )}
    </>
}
// 一個(gè)黑盒組件
function ChildComponent(props){
    return <>...</>
}
// 為了維護(hù)它的狀態(tài)而包裝的組件
function ChildComponentWrap(props){
   // states
   // effects
   return <ChildComponent
               // ...state
               // ...callback
   />
}

作為一個(gè)很擅長堆屎山的人,嘗試過下面這樣的代碼,但是由于 react hook 的固定規(guī)則,元素?cái)?shù)量發(fā)生變化的時(shí)候,必然報(bào)錯(cuò)。(相信一些 react 新手肯定掉過這個(gè)坑)

function Parent(){
    // states
    // effects 
    return <>
        {list.map(item =>{
              useState()
              useEffect(()=>{}, [xxx]);
              return <ChildComponentWrap
                    key={item.key} 
                   // ...state
                   // ...callback
                   // 這里其實(shí)可能很多
                />
            }
        )}
    </>
}

所以需要某種方法,讓它支持內(nèi)聯(lián) hook,就有了 inlineHook 的這樣一個(gè)工具,原理很簡單,它創(chuàng)造了一個(gè)組件,并把你的代碼塊運(yùn)行在里面,所以里面可以用 hook,當(dāng)?shù)谝粎?shù)為 string 的時(shí)候,作為組件的 key。

function Parent(){
    // states
    // effects 
    return <>
        {list.map(item => 
            inlineHook(item.key, () => {
              useState()
              useEffect(()=>{}, [xxx]);
              return <ChildComponent
                   // ...state
                   // ...callback
                />
            })
        )}
    </>
}

二、條件副作用

錯(cuò)誤代碼

function AComponent(){
    // 注意這里,condition false true 轉(zhuǎn)換的時(shí)候會(huì)報(bào)錯(cuò)
    if(condition){
        useEffect(()=>{}, [])
    }
    return <>...</>
}

使用 inlineHook,基于條件掛載組件的方式就可以實(shí)現(xiàn)條件 hook。

function AComponent(){
    return <>
        {condition && inlineHook(()=>{
            useEffect(()=>{}, []);
        })}
        ...
    </>
}

再考慮一個(gè)這樣的 case:有個(gè)長鏈推送文本,當(dāng)文本變化的時(shí)候,將文本變?yōu)榫G色,持續(xù) 3s 之后恢復(fù)黑色。在你可以接受的情況下,何必為了小小一個(gè) text 變色去創(chuàng)建一個(gè)組件呢?

const text = useReceiveMessage();
return <>
    <div>別的什么東西</div>
    {
        text && inlineHook(text, () => {
            const { value } = useCountdown(3);
            return <span style={{ color: value ? 'green' : '#000' }}>
                {text}
            </span>
        })
    }
    <div>別的什么東西</div>
<>

三、表單聯(lián)動(dòng)

想象這樣一個(gè)場景,你有一個(gè)條件表單。

  1. A 會(huì)限制 B 的選項(xiàng)
    • A 選 'a' 時(shí),B 可選 '1'、'2'、'3';
    • A 選 'b' 時(shí),B 可選 '3'、'4'、'5';
    • A 選 'c' 時(shí),B 可選 '5'、'6'、'7';
  2. 當(dāng) A 切換的時(shí)候,你需要清除已選中的 B選項(xiàng)(注意上面的 B可選項(xiàng)是有重疊的,有些值可以保留)
return <Form>
    <Form.Select
        field='A'
        optionList={['a','b','c']}
    />
    {* 可能離得很遠(yuǎn) *}
    <Form.Select
        field='B'
        multiple  // 多選
        optionList={[...]} // 想辦法映射一下選項(xiàng)
    />
</Form>

思考一下,怎么弄。

可以在 A 的 onChange 里面處理一下

<Form.Select
    field='A'
    optionList={['a','b','c']}
    onChange={(v) => { // 可以提出去,但是邏輯也很跳躍
        const BOptionList = getBOptionList(v);
        const newValues = ... 
        const values = formApi.getValue('B')
        if(!isEqual(values,newValues)){
           formApi.setValue('B', newBValue)
        }
    }}
/>
{* 可能離得很遠(yuǎn),不一定會(huì)關(guān)注到這兩個(gè)表單項(xiàng)的關(guān)系 *}
 <Form.Select
    field='B'
    multiple  // 多選
    optionList={[...]} // 想辦法映射一下選項(xiàng)
/>

也可以拆組件,對嗎?如我之前所說,你需要在組件間跳躍,上下文 props 需要傳遞。

function FieldB(props){
    const AValue = useFieldValue("A");
    const formApi = useFormApi();
    const BOptionList = getBOptionList(AValue);
    useEffect(() => {
        const values = formApi.getValue("B");
        // 檢查一下 B 的值在不在 optionList 里面,不在就清除掉
        const newValues = ... // 想辦法處理出來
        if(!isEqual(values, newValues)){
            form.setValue("B", newValues);
        }
    }, [AValue]);
    return <Form.Select
        field='B'
        optionList={BOptionList}
    />
}

使用 inlineHook 之后,大概就是這樣。這并不是說這是什么好辦法,這是一個(gè)偏好問題,但至少,不需要一個(gè)新的組件(當(dāng)你需要頻繁修改的時(shí)候,過多的組件跳轉(zhuǎn)會(huì)影響編碼效率),組件的使用與聯(lián)動(dòng)關(guān)系可以放得近。

return <Form>
    <Form.Select
        field='A'
        optionList={['a','b','c']}
    />
    {* 可能離得很遠(yuǎn) *}
    {inlineHook(()=>{
        const AValue = useFieldValue("A");
        const formApi = useFormApi();
        useEffect(() => {
            const BOptionList = getBOptionList(v);
            const values = formApi.getValue("B");
            // 檢查一下 B 的值在不在 optionList 里面,不在就清除掉
            const newValues = ... // 想辦法處理出來
            if(!isEqual(values, newValues)){
                form.setValue("B", newValues);
            }
        }, [AValue]);
        return <Form.Select
            field='B'
            optionList={[...]} // 想辦法映射一下選項(xiàng)
        />
    }}
</Form>

四、類組件里面不能使用 hook 嗎

雖然這年頭應(yīng)該沒有什么人會(huì)用類組件了,如下,這個(gè)用法也是寫文章的時(shí)候才想起來的,我覺得是可行的。

class AComponent extends Component{
    state = {
        a: 1 
    }
    render(){
       return inlineHook(() => {
               const [b, setB] = useState(2);
               this.state.a;
               useEffect(() => {
               }, [this.state.a, b])
               return <>...</>
       })
    }
}

用法

return <>
    {* 直接嵌入 *}
    {inlineHook(()=>{
        useState();
        useEffect(()=>{}, []);
        return <>可以返回elem渲染</>
    })}
    {* 條件hook *}
    {
        condition && inlineHook(()=>{
            useEffect(()=>{},[])
            return <>可以返回elem渲染</>
        })
    }
    {* 列表 *}
    {
        list.map(item=>
            inlineHook(item.key, ()=>{
                useState();
                useEffect(()=>{}, []);
                return <>可以返回elem渲染</>;
            }))
    }
</>

好處

  1. 減少一次性 Wrapper 組件
  2. 在編碼早期,頻繁修改代碼的時(shí)候,可以盡快驗(yàn)證,而不需要?jiǎng)?chuàng)建一個(gè)新的組件

壞處

  1. 你需要繞過這個(gè)文件的 react-hook eslint 檢查,破壞了規(guī)范
  2. 代碼會(huì)越寫越長,人會(huì)越來越懶(用爽了都不想重構(gòu)了)

源碼

import React, { createElement, isValidElement } from 'react';
function Hook({ fn }: { fn: () => any }) {
  const res = fn();
  return isValidElement(res) ? res : null;
}
const NullComponent = () => null;
/**
 * 掛載 hook,當(dāng)你不想為它寫一個(gè)組件或者不知掛哪個(gè)組件上的時(shí)候
 * @param fn 傳入一個(gè) hook 函數(shù)
 * @returns
 */
export function inlineHook(fn: () => any): React.ReactElement;
export function inlineHook(key: string, fn: () => any): React.ReactElement;
export function inlineHook(...args: any[]) {
  const [a, b] = args;
  if (typeof a === 'function') {
    return createElement(Hook, {
      fn: a,
    });
  } else if (typeof a === 'string') {
    return createElement(Hook, {
      key: a,
      fn: b,
    });
  } else {
    return createElement(NullComponent, {});
  }
}

總結(jié) 

到此這篇關(guān)于React內(nèi)聯(lián)hook的文章就介紹到這了,更多相關(guān)React內(nèi)聯(lián)hook內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • react合成事件與原生事件的相關(guān)理解

    react合成事件與原生事件的相關(guān)理解

    本文主要介紹了react合成事件與原生事件的相關(guān)概念,幫助大家區(qū)分這兩種事件,學(xué)習(xí)react的同學(xué)不妨了解下
    2021-05-05
  • react-beautiful-dnd拖拽排序功能的實(shí)現(xiàn)過程

    react-beautiful-dnd拖拽排序功能的實(shí)現(xiàn)過程

    這篇文章主要介紹了react-beautiful-dnd拖拽排序功能的實(shí)現(xiàn)過程,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • React事件機(jī)制源碼解析

    React事件機(jī)制源碼解析

    這篇文章主要介紹了React事件機(jī)制源碼解析的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用React框架,感興趣的朋友可以了解下
    2021-04-04
  • Express+React+Antd實(shí)現(xiàn)上傳功能(前端和后端)

    Express+React+Antd實(shí)現(xiàn)上傳功能(前端和后端)

    這篇文章主要介紹了Express+React+Antd實(shí)現(xiàn)上傳功能(前端和后端),本文通過示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-04-04
  • 使用Jenkins部署React項(xiàng)目的方法步驟

    使用Jenkins部署React項(xiàng)目的方法步驟

    這篇文章主要介紹了使用Jenkins部署React項(xiàng)目的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • React中的Component組件詳解

    React中的Component組件詳解

    本章節(jié),我們將一起探討 React 中類組件和函數(shù)組件的定義,不同組件的通信方式,以及常規(guī)組件的強(qiáng)化方式,幫助你全方位認(rèn)識 React 組件,從而對 React 的底層邏輯有進(jìn)一步的理解,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • React庫之react-beautiful-dnd介紹及其使用過程

    React庫之react-beautiful-dnd介紹及其使用過程

    在使用React構(gòu)建Web應(yīng)用程序時(shí),拖拽功能是一項(xiàng)常見需求,為了方便實(shí)現(xiàn)拖拽功能,我們可以借助第三方庫react-beautiful-dnd,本文將介紹react-beautiful-dnd的基本概念,并結(jié)合實(shí)際的項(xiàng)目代碼一步步詳細(xì)介紹其使用過程,需要的朋友可以參考下
    2023-11-11
  • React中使用react-player 播放視頻或直播的方法

    React中使用react-player 播放視頻或直播的方法

    這篇文章主要介紹了React中使用react-player 播放視頻或直播,本文教大家如何使用react框架及創(chuàng)建實(shí)例的代碼,本文內(nèi)容簡短給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • React父子組件間的傳值的方法

    React父子組件間的傳值的方法

    在單頁面里面,父子組件傳值是比較常見的,這篇文章主要介紹了React父子組件間的傳值的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-11-11
  • React中useEffect函數(shù)的使用詳解

    React中useEffect函數(shù)的使用詳解

    useEffect是React中的一個(gè)鉤子函數(shù),用于處理副作用操作,這篇文章主要為大家介紹了React中useEffect函數(shù)的具體用法,希望對大家有所幫助
    2023-08-08

最新評論

绥阳县| 尚志市| 若尔盖县| 巢湖市| 乐清市| 霸州市| 遂宁市| 胶州市| 名山县| 昌黎县| 确山县| 遵义县| 周至县| 土默特右旗| 泸西县| 安泽县| 洪泽县| 吉安县| 长乐市| 紫金县| 宜城市| 虞城县| 丰城市| 阿拉善盟| 岢岚县| 通化县| 图木舒克市| 沂南县| 镇康县| 岳阳市| 黑龙江省| 务川| 本溪市| 乌苏市| 清镇市| 罗源县| 扎囊县| 龙山县| 大港区| 东山县| 平武县|