Случай не относится к хукам, он будет таким же для компонента класса и setState
в случае, если transformText
и onChange
должны быть извлечены из класса.Нет необходимости извлекать однострочные функции, поэтому можно предположить, что реальные функции достаточно сложны, чтобы оправдать извлечение.
Прекрасно иметь функцию преобразования, которая принимает значение в качестве аргумента.
Что касается обработчика событий, он должен иметь ссылку на setState
, это ограничивает способы его использования.
Распространенным рецептом является использование функции обновления состояния.В случае, если ему нужно принять дополнительное значение (например, значение события), это должна быть функция высшего порядка.
const transformText = text => text.toUpperCase();
const onChange = val => _prevState => ({ text: val });
function SomeComponent(props) {
const [text, setText] = useState('');
return (
<input type="text" onChange={e => setText(onChange(e.currentValue.text)} value={transformText(text)} />
);
}
Этот рецепт не выглядит полезным в этом случае, потому что оригинальный onChange
не делаетмного.Это также означает, что извлечение не было оправдано.
Способ, специфичный для хуков, заключается в том, что setText
может быть передан как обратный вызов, в отличие от this.setState
.Так что onChange
может быть функцией более высокого порядка:
const transformText = text => text.toUpperCase();
const onChange = setState => e => setState({ text: e.currentValue.text });
function SomeComponent(props) {
const [text, setText] = useState('');
return (
<input type="text" onChange={onChange(setText)} value={transformText(text)} />
);
}
Если целью является уменьшение повторного рендеринга детей, вызванного изменениями в onChange
prop, onChange
следует запомнить с useCallback
или useMemo
.Это возможно, поскольку useState
функция установки не изменяется между обновлениями компонента:
...
function SomeComponent(props) {
const [text, setText] = useState('');
const memoizedOnChange = useMemo(() => onChange(setText), []);
return (
<input type="text" onChange={memoizedOnChange} value={transformText(text)} />
);
}
То же самое можно достичь, не извлекая onChange
и используя useCallback
:
...
function SomeComponent(props) {
const [text, setText] = useState('');
const onChange = e => setText({ text: e.currentValue.text });
const memoizedOnChange = useCallback(onChange, []);
return (
<input type="text" onChange={memoizedOnChange} value={transformText(text)} />
);
}