【问题标题】:UseEffect or throwing logic in the functional componentUseEffect 或在功能组件中抛出逻辑
【发布时间】:2021-04-23 05:42:15
【问题描述】:

我是 React 新手。我知道 UseEffect 对于保持相关数据彼此同步很有用。

示例 1:

每当道具 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 在这种情况下是否提供任何性能提升?比如尽量减少重新加载的次数。

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    这两种方法都有效。第二个可能读起来更清楚一些,因为根本没有状态,并且值是直接从道具计算的,但是计算在主函数体而不是在效果回调中意味着计算将在每次渲染时调用,而不是仅在 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 的一个潜在缺点是它不是即时的——状态更新需要一些时间。这有时会导致屏幕闪烁和子组件出现异步问题。

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-26
        • 1970-01-01
        • 2016-02-22
        • 2019-09-04
        • 2020-02-02
        • 2022-01-14
        • 1970-01-01
        相关资源
        最近更新 更多