[英]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.