功能组件中的 UseEffect 或抛出逻辑

时间:2021-04-23 05:42:15

标签: reactjs react-hooks

我是 React 的新手。我知道 UseEffect 在保持相关数据彼此同步方面很有用。

示例 1:

每当 prop rawDateInput 更新时,下面的代码都会更新 calendarDateinputDate

const DATE_FORMAT = 'MM/DD/YY';

type Props = {
    name: string;
    label: string;
    required?: boolean;
    value?: Date | undefined;
    readOnly?: boolean;
};
const DatePicker: FunctionComponent<Props> = ({ name, value: rawDateInput, label, required, readOnly }) => {
    const inputId = name.replace(/[\W]+/g, '_');

    const [calendarDate, setCalendarDate] = useState<Date | null>();
    const [inputDate, setInputDate] = useState<string>('');
 
    useEffect(() => {
        const momentDate = moment(rawDateInput);
        setCalendarDate(momentDate.toDate());
        setInputDate(momentDate.format(DATE_FORMAT));
    }, [rawDateInput]);

    return (
        <Fragment>
            <Label htmlFor={inputId} text={label} />{required && <span className='text-danger'>*</span>}
                <input
                    id={inputId}
                    name={name}
                    value={inputDate}
                    readOnly={readOnly}
                    placeholder={DATE_FORMAT}
                    maxLength={8}
                />
                <Calendar value={calendarDate}  />
        </Fragment>
    );
}
export default DatePicker;

示例 2:

下面的代码截图完成了与示例 1 相同的事情,但它只是将逻辑放在函数组件内部,而不是调用 useEffect 钩子。

const DATE_FORMAT = 'MM/DD/YY';

type Props = {
    name: string;
    label: string;
    required?: boolean;
    value?: Date | undefined;
    readOnly?: boolean;
};
const DatePicker: FunctionComponent<Props> = ({ name, value: rawDateInput, label, required, readOnly }) => {
    const inputId = name.replace(/[\W]+/g, '_');

    const momentDate = moment(rawDateInput);
    const calendarDate = momentDate.toDate();
    const inputDate = momentDate.format(DATE_FORMAT);

    return (
        <Fragment>
            <Label htmlFor={inputId} text={label} />{required && <span className='text-danger'>*</span>}
                <input
                    id={inputId}
                    name={name}
                    value={inputDate}
                    readOnly={readOnly}
                    placeholder={DATE_FORMAT}
                    maxLength={8}
                />
                <Calendar value={calendarDate}  />
        </Fragment>
    );
}
export default DatePicker;

我的问题是:

  1. 当我们有依赖于 prop 的数据时,我们应该使用 UseEffect(示例 #1)还是简单地将逻辑放在函数组件中(示例 #2)?

  2. 在这种情况下,UseEffect 是否提供任何性能提升?比如尽量减少重新加载的次数。

2 个答案:

答案 0 :(得分:1)

两种方法都有效。第二个可能更容易阅读,因为根本没有状态,并且值是直接从 props 计算的,但是在主函数体中而不是在效果回调中进行计算将意味着计算将在每次渲染时调用,而不是仅在 prop 更改时调用。

但是有一种更好的方法可以在不使用 useEffect 或状态的情况下实现这一点,即使用 useMemo

const momentDate = useMemo(() => moment(rawDateInput), [rawDateInput]);
const calendarDate = useMemo(() => momentDate.toDate(), [momentDate]);
const inputDate = useMemo(() => momentDate.format(DATE_FORMAT), [momentDate]);
<块引用>

在这种情况下,UseEffect 是否提供任何性能提升?比如尽量减少重新加载的次数。

它会尽量减少对 moment 的调用,但也会增加重新渲染的次数,因为道具更改将导致效果回调运行、状态更改和另一次渲染。 useEffect 的一个潜在缺点是它不是即时的 - 状态更新需要一些时间。这偶尔会导致屏幕闪烁和子组件出现异步问题。

答案 1 :(得分:0)

<块引用>

当我们有依赖于 prop 的数据时,我们应该使用 UseEffect (Example #1) 或者简单地将逻辑放在函数中 组件(示例#2)?

将传递的 props 的派生值存储到本地状态实际上是 React 中的一种反模式。它容易出现同步问题(即陈旧状态)。直接消费传入的 props 并渲染结果即可。

<块引用>

在这种情况下,UseEffect 是否提供任何性能提升?像 尽量减少重新加载的次数。

没有。如果有的话,它会添加更多渲染,因为需要额外的渲染周期才能根据更新的本地状态进行渲染。如果您希望提高性能,您可以使用依赖于所使用的特定道具的 useMemo React 钩子记住第二个代码段中的计算。