Я думал о том, как закодировать очиститель TailwindCSS в React. Поскольку 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 вот так? Спасибо 🙏 .



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это правильно или хорошая практика, если я так использую 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
Спасибо @kind user 🙏. Итак, если проект будет больше и поскольку useMemo занимает память, функция tw() всегда только объединяет строки, так какой из них вы предпочитаете? использовать useMemo или нет? Спасибо 😊 .
@mnrendra Лично я бы не стал использовать useMemo для соединения строк. Вернее, как я уже упоминал выше — на сопоставлении или уменьшении огромных массивов. Но все же это зависит от того, сколько элементов вы соединяете. Если о сотнях - достойно точно. Если только пару - то нет. (Комментарий отредактирован)
Проблема здесь в том, что React будет повторно отображать компонент каждый раз, когда его состояние изменяется. (каждый раз, когда вы устанавливаете текст).
Если вы хотите предотвратить это, посмотрите, действительно ли вам нужен этот повторный рендеринг, поэтому для чего вам действительно нужен входной текст?
вы НЕ ДОЛЖНЫ использовать состояние здесь, чтобы использовать входное значение. вы можете вызвать другую функцию при изменении, которая не будет обновлять состояние, и использовать там входное значение для всего, что вам нужно. Например:
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>
)
}
Вызов его внутри синтаксиса элемента JSX аналогичен вызову перед выражением
return, сохранению результата во временной переменной и передаче его в качестве значения атрибута. Нет разницы. Конечно, правила хуков все еще применяются, вы не можете сделать это в условном рендеринге.