为什么将组件存储为状态值是不好的做法?
const [Component, setComponent] = useState<JSX.Element>(<Empty />);
假设我想根据许多不同的标准(所有标准都是互斥的)有条件地呈现一个组件.但在实际渲染之前,我想添加一个取消保镖(在x
毫秒不活动后延迟渲染).我不一定会这样做,但它似乎更直观,而且只将组件指定为状态值(在此场景中)代码更少.我可以将状态设置为保存一个文本值,在任何地方引用该文本值,并设置一个映射变量将该字符串映射到一个组件.但这似乎没有必要.I've read online that it's bad practice,你应该只把数据放入状态,但似乎每个人都很方便省略了why,这是一个糟糕的做法.Nothing in the docs似乎也表明这是一种糟糕的做法.
这里有一个有效的例子,希望能说明为什么将组件设置在状态很方便.Message
个组件中的每个组件都有React.memo
个标记,因此它们的props 不可能发生变化:
import React, { useState, useEffect } from 'react';
import useDebounce from '../../hooks/useDebounce';
import {
TooShort,
NoPrompt,
LimitWarning,
LimitReached,
Empty,
} from './Messages';
interface Props {
promptAreaTouched: boolean;
promptText: string;
debounceTimeout?: number;
}
const DEBOUNCE_TIMEOUT = 2000;
const SHORT_PROMPT_LENGTH = 5;
const APPROACHING_PROMPT_LENGTH = 40;
const MAX_PROMPT_LENGTH = 50;
const PromptLengthMessage = ({
promptAreaTouched,
promptText,
debounceTimeout = DEBOUNCE_TIMEOUT,
}: Props) => {
const [Component, setComponent] = useState<JSX.Element>(<Empty />);
const DebouncedComponent = useDebounce(Component, debounceTimeout);
const numWords = promptText.split(/\s+/).length;
const isEmpty = promptAreaTouched && promptText.length === 0;
const isTooShort = promptAreaTouched && numWords <= SHORT_PROMPT_LENGTH;
const limitWarning =
numWords >= APPROACHING_PROMPT_LENGTH && numWords < MAX_PROMPT_LENGTH;
const limitReached = numWords >= MAX_PROMPT_LENGTH;
useEffect(() => {
switch (true) {
case isEmpty:
setComponent(<NoPrompt />);
break;
case isTooShort:
setComponent(<TooShort />);
break;
case limitWarning:
setComponent(<LimitWarning />);
break;
case limitReached:
setComponent(<LimitReached />);
break;
default:
setComponent(<Empty />);
}
}, [promptText]);
return DebouncedComponent === Component ? DebouncedComponent : <Empty />;
};
export default PromptLengthMessage;