我正在考虑如何在 React 中编写 TailwindCSS clean 代码。由于 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
被重新调用。
因此,我决定使用
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
记忆东西并且需要内存。
考虑下面的例子。在第一种情况下,如果没有
useMemo
,每次 tw
重新渲染时,App
函数都会被 称为,以计算新的
className
。但是,如果使用 useMemo
(带有空的 依赖数组),则 tw
不会被调用,并且即使 className
重新渲染,新的
App
也不会被计算,因为基本的记忆。它只会在组件安装时被调用一次。 结论 - 使用
useMemo
是一个很好的做法,但对于繁重的操作来说,比如映射或减少巨大的数组。
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
如果你想防止这种情况发生,那么看看你是否真的需要重新渲染,那么你真正需要输入文本的目的是什么?
您不必在此处使用状态来使用输入值。 您可以在更改时调用另一个函数,该函数不会更新状态,并使用其中的输入值来满足您的需要。 例如:
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>
)
}