成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

喔!React19 中的 Hook 可以寫在 If 條件判斷中了。Use 實踐:點擊按鈕更新數(shù)據(jù)

開發(fā) 前端
本文模擬的實踐案例為點擊按鈕更新數(shù)據(jù)。這在開發(fā)中是一個非常常見的場景。我們直接用 React 19 新的開發(fā)方式來完成這個需求。

接下來,我們將會以大量的實踐案例來展開 React 19 新 hook 的運用。

本文模擬的實踐案例為點擊按鈕更新數(shù)據(jù)。這在開發(fā)中是一個非常常見的場景。

案例完成之后的最終演示效果圖如下:

我們直接用 React 19 新的開發(fā)方式來完成這個需求。

一、基礎(chǔ)實現(xiàn)

首先創(chuàng)建一個方法用于請求數(shù)據(jù)。

const getApi = async () => {
  const res = await fetch('https://api.chucknorris.io/jokes/random')
  return res.json()
}

這里一個非常關(guān)鍵的地方就在于,當(dāng)我們要更新的數(shù)據(jù)時,我們不再需要設(shè)計一個 loading 狀態(tài)去記錄數(shù)據(jù)是否正在發(fā)生請求行為,因為 Suspense 幫助我們解決了 Loading 組件的顯示問題。

與此同時,use() 又幫助我們解決了數(shù)據(jù)獲取的問題。那么問題就來了,這個就是,好像我們也不需要設(shè)計一個狀態(tài)去存儲數(shù)據(jù)。那么應(yīng)該怎么辦呢?

這里有一個非常巧妙的方式,就是把創(chuàng)建的 promise 作為狀態(tài)值來觸發(fā)組件的重新執(zhí)行。每次點擊,我們都需要創(chuàng)建新的 promise

代碼如下:

// 記住這個初始值
const [api, setApi] = useState(null)

這個時候,當(dāng)我們點擊事件執(zhí)行時,則只需要執(zhí)行如下代碼去觸發(fā)組件的更新。

function __clickToGetMessage() {
  // 每次點擊,都會創(chuàng)建新的 promise
  setApi(getApi())
}

getApi() 執(zhí)行,新的請求會發(fā)生。他的執(zhí)行結(jié)果,又返回了一個新的 promise。

因此,點擊之后會創(chuàng)建的新 promise 值,api 此時就會作為狀態(tài)更改觸發(fā)組件的更新。

完整代碼如下:

export default function Index() {
  const [api, setApi] = useState(null)

  function __clickToGetMessage() {
    setApi(getApi())
  }

  return (
    <div>
      <div id='tips'>點擊按鈕獲取一條新的數(shù)據(jù)</div>
      <button onClick={__clickToGetMessage}>獲取數(shù)據(jù)</button>

      <div className="content">
        <Suspense fallback={<div>loading...</div>}>
          <Item api={api} />
        </Suspense>
      </div>
    </div>
  )
}

const Item = (props) => {
  if (!props.api) {
    return <div>nothing</div>
  }

  const joke = use(props.api)
  return (
    <div className='a_value'>{joke.value}</div>
  )
}

案例寫完之后。我們基本上就能夠?qū)崿F(xiàn)最開始截圖中的交互效果了。但是現(xiàn)別急,還沒有完。我們還需要進(jìn)一步分析一下這個案例。

二、案例分析

這里我們需要注意觀察兩個事情。

一個是觀察當(dāng)前組件更新,更上層的父組件是否發(fā)生了變化。我們可以在 App 組件中執(zhí)行一次打印。

此時可以發(fā)現(xiàn),當(dāng)我們重新請求時,當(dāng)前組件更新,但是上層組件并不會重新執(zhí)行。

我們可以出得結(jié)論:更簡潔的狀態(tài)設(shè)計,有利于命中 React 默認(rèn)的性能優(yōu)化規(guī)則。

具體的規(guī)則請在 React 知命境合集中查看。

更簡潔的狀態(tài)設(shè)計,也是 React 19 所倡導(dǎo)的開發(fā)思路。

另外一個事情,是我們要特別特別注意觀察子組件 Item 的實現(xiàn)。

首先因為我們初始化時,給 api 賦予的默認(rèn)值是 null。

// 記住這個初始值
const [api, setApi] = useState(null)

之后,我們就將 api 傳給了子組件 Item。

<Item api={api} />

然后在 Item 組件的內(nèi)部實現(xiàn)中,因為我們直接把 api 傳給了 use,那么此時直接執(zhí)行肯定會報錯。

const joke = use(props.api)

要注意的是,我們剛才說,使用 Suspense 會捕獲子組件的異常,但是不是捕獲所有異常,它只能識別 promise 的異常。因此,這里的報錯會直接影響到整個頁面。

所以,為了處理好初始化時傳入 api 值為 null,我在內(nèi)部實現(xiàn)代碼邏輯中,使用了 if 判斷該條件,然后執(zhí)行了一次 return。我試圖讓 use(null) 得不到執(zhí)行的時機。

const Item = (props) => {
  if (!props.api) {
    console.log('初始化時,api == null')
    return <div>nothing</div>
  }

  const joke = use(props.api)
  return (
    <div className='a_value'>{joke.value}</div>
  )
}

那么,我的意圖是否能成功呢?

我們在 return 后面插入一個 console.log 來觀察代碼的執(zhí)行情況,代碼如下:

const Item = (props) => {
  if (!props.api) {
    console.log('初始化時,api == null')
    return <div>nothing</div>
  }
  
  console.log('初始化時這里是否執(zhí)行');

  const joke = use(props.api)
  return (
    <div className='a_value'>{joke.value}</div>
  )
}

演示效果如下圖所示:

我們發(fā)現(xiàn),當(dāng)我反復(fù)刷新頁面,讓初始化流程執(zhí)行時,return 后面的代碼并不會執(zhí)行。

再然后,我們新增一點內(nèi)容,比如在 return 后面使用一個 useEffect。

const Item = (props) => {
  if (!props.api) {
    console.log('初始化時,api == null')
    return <div>nothing</div>
  }

  useEffect(() => {
    console.log('xxx')
  }, [])
  console.log('初始化時這里是否執(zhí)行')

  const joke = use(props.api)
  return (
    <div className='a_value'>{joke.value}</div>
  )
}

然后演示再看看。我們發(fā)現(xiàn) effect 也不會執(zhí)行。然后我們還可以搞點好玩的。

Item 代碼改造如下:

const Item = (props) => {
  if (!props.api) {
    const [count, setCount] = useState(0)
    console.log('初始化時,api == null')
    return <div onClick={() => setCount(count + 1)}>nothing, {count}</div>
  }

  console.log('初始化時這里是否執(zhí)行')

  const joke = use(props.api)
  return (
    <div className='a_value'>{joke.value}</div>
  )
}

注意看,我們在 if 條件判斷中,單獨創(chuàng)建了一個 useState,并在對應(yīng)的元素上添加了一個讓 count 遞增的交互。

這段在之前版本的開發(fā)中一定會觸發(fā)語法錯誤提示的代碼。

最終也是能勉強運行,但是代碼會瘋狂報錯。

代碼演示結(jié)果如下:

然后,我繼續(xù)一個騷操作,我在 if 中條件判斷中,使用 useEffect,代碼如下:

const Item = (props) => {
  if (!props.api) {
    useEffect(() => {
      console.log('useEffect 在 if 中執(zhí)行')
    }, [])
    return <div>nothing</div>
  }

  console.log('初始化時這里是否執(zhí)行')

  const joke = use(props.api)
  return (
    <div className='a_value'>{joke.value}</div>
  )
}

也能正常執(zhí)行。觀察一下演示效果:

結(jié)論:

很明顯,react 19 的 hook 在底層發(fā)生了一些優(yōu)化更新,我們可以不用非得把所有的 hook 都放在函數(shù)組件的最前面去執(zhí)行了。

在 React 19 中,我們可以把 hook 放到 return 之后,也可以放到條件判斷中去執(zhí)行。

但是,我們一定要注意的是,并非表示我們可以隨便亂寫。當(dāng)條件互斥時,狀態(tài)之間如果存在不合理的耦合關(guān)系,依然不能正常執(zhí)行。我們列舉兩個案例來觀察這個事情。

第一個案例,我們依然在 if 中執(zhí)行一個 useEffect,但是不同的是,我把在 if 之外的狀態(tài) counter 作為依賴項傳入。

代碼如下。

const Item = (props) => {
  const [counter, setCounter] = useState(0)
  if (!props.api) {
    useEffect(() => {
      console.log('useEffect 在 if 中執(zhí)行')
    }, [counter])
    return <div>nothing</div>
  }

  console.log('初始化時這里是否執(zhí)行')

  const joke = use(props.api)
  return (
    <div className='a_value' onClick={() => setCounter(counter + 1)}>{joke.value}</div>
  )
}

此時一個很明顯的問題就是,if 內(nèi)部在 UI 邏輯上本和外部是互斥的關(guān)系,但是我們在狀態(tài)邏輯上卻相互關(guān)聯(lián)。因此這個之后,代碼執(zhí)行就會報錯,明確的告訴你這種寫法不合理。

第二個案例。我在條件判斷中,定義了一個狀態(tài) bar,但是我并沒有在 if 中 return,而是繼續(xù)往后執(zhí)行。代碼如下:

const [counter, setCounter] = useState(0)
if (counter == 0) {
  const [bar, setBar] = useState('bar')
  console.log('bar', bar)
}

const [foo, setFoo] = useState('foo')

console.log('foo', foo)
return (
  <button notallow={() => setCounter(counter + 1)}>counter ++ foo: {foo}</button>
)

這個現(xiàn)象的解釋就是我們之前在面試時經(jīng)常會聊的一個話題:為什么不能將 hook 放在條件判斷中去執(zhí)行。

由于在 fiber 中,是通過有序鏈表的方式來存儲 hook 的值。因此,當(dāng)隨著 counter 遞增,條件判斷中的 hook 不再執(zhí)行,但是它的值已經(jīng)被緩存上了,后續(xù)的執(zhí)行中,foo 就變成了第 1 個 hook,從而導(dǎo)致 foo 獲取到了 bar 的值。

好在 react 19 對這種情況做出了明確的判斷,當(dāng)你這樣寫時,代碼會明確報錯終止程序的運行。所以在開發(fā)過程中我們也不用特別去區(qū)分什么情況下不能用。

三、需求變動

現(xiàn)在我們做一點小小的需求變動。

在之前的案例實現(xiàn)中,組件代碼初始化時,并沒有初始化請求一條數(shù)據(jù)。因此,默認(rèn)渲染結(jié)果是 nothing。

此時,我們?nèi)绻MM件首次渲染時,就一定要請求一次接口,我們的代碼應(yīng)該怎么改呢?

在以前版本的實現(xiàn)中,接口數(shù)據(jù)的觸發(fā)方式不同,因此我們需要分別處理這兩種觸發(fā)時機。

初始化時的數(shù)據(jù)請求,我們利用 useEffect 來實現(xiàn)。

function PreIndex() {
  const [data, setData] = useState({value: ''})
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    api().then(res => {
      setData(res)
      setLoading(false)
    })
  }, [])
}

按鈕點擊事件觸發(fā)時,我們通過回調(diào)函數(shù)來實現(xiàn)。

function PreIndex() {
  const [data, setData] = useState({value: ''})
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    api().then(res => {
      setData(res)
      setLoading(false)
    })
  }, [])

  function _clickHandler() {
    setLoading(true)
    api().then(res => {
      setData(res)
      setLoading(false)
    })
  }

  ...
}

然而,在新的開發(fā)方式中,我們只需要在上面的案例做一個非常小的變動,那就是把 api 的參數(shù)使用 getApi() 去初始化,而不是 null,就可以做到了。

// 只需要改這一點代碼
const [api, setApi] = useState(getApi())

改完之后,演示效果如下:

非常的方便省事。

當(dāng)然這樣寫會造成冗余的接口請求執(zhí)行。因此我們可以稍作調(diào)整就可以了。

這里需要根據(jù)需求調(diào)整,案例只做演示。

const _initApi = getApi()
function Index() {
  const [api, setApi] = useState(_initApi)
  ...
}

OK,今天的案例就介紹到這里,后續(xù)的章節(jié)我們還會繼續(xù)更多的實戰(zhàn)案例的分析。

責(zé)任編輯:姜華 來源: 這波能反殺
相關(guān)推薦

2024-06-12 07:44:28

2024-12-06 11:22:27

2024-02-20 07:44:43

2024-04-28 09:01:06

React 19更新前端

2024-06-05 08:40:53

2024-05-08 08:50:39

React19模式UI

2024-09-20 08:14:16

2025-02-17 12:24:06

2024-06-13 09:46:50

React19版本更新Vue

2024-06-18 09:36:45

2024-04-10 07:49:37

React 19use 鉤子Suspense

2024-12-09 08:21:49

2024-02-22 17:54:30

React編譯器團(tuán)隊

2024-05-11 09:38:05

React編譯器React 19

2022-04-14 11:50:39

函數(shù)組件hook

2024-06-19 08:45:13

2024-12-16 08:40:51

2024-11-01 08:34:08

2024-10-28 12:46:22

2024-05-17 08:25:06

數(shù)據(jù)驅(qū)動React語言包
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 99pao成人国产永久免费视频 | 久久久不卡网国产精品一区 | 欧美日韩中文在线 | 在线看一区二区 | 久久精品久久久久久 | 久久久蜜桃 | 国产精品99久久久久久大便 | 亚洲一区二区在线视频 | 91成人精品 | 欧美综合精品 | 欧美电影一区 | aaa级片 | 国产精品一区二区不卡 | 成人三级视频 | 美国一级片在线观看 | 羞羞的视频在线看 | 国产精品99免费视频 | 国产三区在线观看视频 | 91免费电影| 亚洲精品视频在线 | 丁香综合 | 中文字幕乱码亚洲精品一区 | 成人在线精品视频 | 久久久国产一区 | 美女视频一区二区三区 | www.中文字幕.com | 九九热这里只有精品在线观看 | 中文字幕乱码一区二区三区 | 欧美综合自拍 | 精品日本中文字幕 | 亚洲国产视频一区二区 | 一级黄色片网站 | 成人一区在线观看 | 中文字幕视频三区 | 欧美日韩三区 | 四虎永久免费地址 | 国产精品久久久久久婷婷天堂 | 久久久久久久国产精品视频 | 日日操日日干 | 国产成年人视频 | 麻豆视频在线看 |