[英]Is good to use React.useMemo or React.useCallback inside component props?
我在考慮如何在 React 中編寫 TailwindCSS cleaner。 由於 Tailwind 是實用程序優先的,它使我們不可避免地以組件結束(例如: className="w-full bg-red-500"
)。 所以,我試圖創建一個這樣的實用程序:
utils/tailwind.ts
const tw = (...classes: string[]) => classes.join(' ')
並在里面調用它:
components/Example.tsx
import { useState } from 'react'
import tw from '../utils/tailwind'
const Example = () => {
const [text, setText] = useState('')
return (
<div>
<input onChange={(e: any) => setText(e.target.value)} />
<div
className={tw(
'w-full',
'h-full',
'bg-red-500'
)}
>
hello
</div>
</div>
)
}
但是,它會導致tw()
在text
state 更新時一如既往地被重新調用。
因此,我決定使用 useMemo 包裝tw()
useMemo
以防止重新調用,因為tw()
始終返回相同的值。 但是代碼是這樣的:
import { useState, useMemo } from 'react'
import tw from '../utils/tailwind'
const Example = () => {
const [text, setText] = useState('')
return (
<div>
<input onChange={(e: any) => setText(e.target.value)} />
<div
className={useMemo(() => tw(
'w-full',
'h-full',
'bg-red-500'
), [])}
>
hello
</div>
</div>
)
}
如果我這樣使用useMemo
是正確的還是好的做法? 謝謝你。
如果我這樣使用 useMemo 是正確的還是好的做法?
簡短的回答 - yes
的。
長答案 - 這取決於。 這取決於手術的重量。 在您的特定情況下,連接幾個字符串可能不會是使useMemo
值得使用的繁重計算 - 最好記住useMemo
會記住東西,它需要 memory。
考慮下面的例子。 在第一種情況下,沒有useMemo
時, tw
function 將在每次App
重新渲染時被調用,以計算新的className
。 但是,如果使用useMemo
(依賴項數組為空),由於基本的className
,即使App
重新呈現,也不會調用tw
並且不會計算新的類名。 它只會在組件安裝時被調用一次。
結論 - 使用useMemo
是一種很好的做法,但更適合繁重的操作,例如映射或減少巨大的 arrays。
export default function App() {
const [_, s] = useState(0);
return (
<div className="App">
<div className={tw(false, 'w-full', 'h-full', 'bg-red-500')}>div1</div>
<div
className={useMemo(
() => tw(true, 'w-full', 'h-full', 'bg-red-500'),
[],
)}
>
div2
</div>
<button onClick={() => s(Math.random())}>re-render</button>
</div>
);
}
游樂場: https://codesandbox.io/s/distracted-liskov-tfm72c?file=/src/App.tsx
這里的問題是 React 會在每次 state 發生變化時重新渲染組件。 (每次你設置文本)。
如果你想防止這種情況發生,那么看看你是否真的需要重新渲染,那么你真正需要輸入文本的目的是什么?
您不必在此處使用 state 來使用輸入值。 您可以在更改時調用另一個 function,它不會更新 state,並根據需要使用那里的輸入值。 例如:
const Example = () => {
const onInputChange = (e) => {
const text = e.target.value
// do something with text
}
return (
<div>
<input onChange={(e: any) => onInputChange(e)} />
<div
className={useMemo(() => tw(
'w-full',
'h-full',
'bg-red-500'
), [])}
>
hello
</div>
</div>
)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.