添加 useEffect 依赖项会破坏代码

问题描述 投票:0回答:1

我有一个用作时间选择器的组件。我还使用 MUI 选项卡来允许用户在全天范围和用户输入的范围之间进行选择。因此,用户可以输入所需的时间,例如从 14:00 到 20:00,如果单击“全天”选项卡,时间选择器间隔将变为 00:00 和 23:59,并且输入将被禁用。

为了监听所选选项卡,我想出了一个 useEffect ,它可以正常工作,直到我添加所有依赖项。

React Hook useEffect has missing dependencies: 'formTimeValues' and 'savedTime'. Either include them or remove the dependency array

    useEffect(() => {
    if (wholeDay) {
      setSavedTime(formTimeValues);
      setValue("defaultDeliveryWindow", wholeDayRange.defaultDeliveryWindow);
    } else {
      setValue("defaultDeliveryWindow", savedTime);
    }
  }, [setValue, wholeDay]);

但是,如果我添加所有缺少的依赖项,我的时间每次都会被重写,并且功能会中断。如何重构 useEffect 或做其他事情来保留功能?

const wholeDayRange = {
  defaultDeliveryWindow: {
    defaultEarliestLoadTime: "00:00",
    defaultLatestLoadTime: "23:59",
  },
};

const TimePickerOwn = ({ wholeDay = false }) => {
  const { t } = useTranslation();
  const { getValues, watch, setValue } = useFormContext();

  const formTimeValues = getValues()?.defaultDeliveryWindow;

  const currentOption = useSelector((state) => state.orderIntake.currentOption);

  const { defaultDeliveryWindow } = currentOption;

  const defaultEarliestLoadTime =
    formTimeValues?.defaultEarliestLoadTime ||
    defaultDeliveryWindow?.defaultEarliestLoadTime;
  const defaultLatestLoadTime =
    formTimeValues?.defaultLatestLoadTime ||
    defaultDeliveryWindow?.defaultLatestLoadTime;

  const watchEarliest = watch(
    "defaultDeliveryWindow.defaultEarliestLoadTime",
    defaultEarliestLoadTime
  );
  const watchLatest = watch(
    "defaultDeliveryWindow.defaultLatestLoadTime",
    defaultLatestLoadTime
  );

  const [savedTime, setSavedTime] = useState({
    defaultEarliestLoadTime,
    defaultLatestLoadTime,
  });

  const [earliestIndex, setEarliestIndex] = useState(
    findCurrentIndex(watchEarliest)
  );

  const [latestIndex, setLatestIndex] = useState(findCurrentIndex(watchLatest));

  useEffect(() => {
    if (wholeDay) {
      setSavedTime(formTimeValues);
      setValue("defaultDeliveryWindow", wholeDayRange.defaultDeliveryWindow);
    } else {
      setValue("defaultDeliveryWindow", savedTime);
    }
  }, [setValue, wholeDay]);

  useEffect(() => {
    const timeOptionsLastIndex = timeOptions.length - 1;
    if (earliestIndex === latestIndex) {
      if (latestIndex === timeOptionsLastIndex) {
        setEarliestIndex(timeOptionsLastIndex - 1);
      } else {
        setLatestIndex((prev) => prev + 1);
      }
    } else if (earliestIndex > latestIndex) {
      setLatestIndex(earliestIndex + 1);
    } else if (latestIndex === 0) {
      setLatestIndex(earliestIndex + 1);
    }
  }, [earliestIndex, latestIndex]);

  useEffect(() => {
    const subscription = watch(({ defaultDeliveryWindow }, { type }) => {
      console.log(defaultDeliveryWindow);

      if (type) return;
      setEarliestIndex(
        findCurrentIndex(defaultDeliveryWindow.defaultEarliestLoadTime)
      );
      setLatestIndex(
        findCurrentIndex(defaultDeliveryWindow.defaultLatestLoadTime)
      );
    });
    return () => subscription.unsubscribe();
  }, [watch]);

  return (
    <>
      <TimeInput
        label={t("orderIntake.earliest")}
        id="startTime"
        time={watchEarliest}
        index={earliestIndex}
        setIndex={setEarliestIndex}
        options={timeOptions.slice(0, -1)}
        registerName="defaultEarliestLoadTime"
        isDisabled={wholeDay}
      />
      <Box marginBottom={2} />
      <TimeInput
        label={t("orderIntake.latest")}
        id="endTime"
        time={watchLatest}
        index={latestIndex}
        setIndex={setLatestIndex}
        options={timeOptions.slice(earliestIndex + 1)}
        registerName="defaultLatestLoadTime"
        isDisabled={wholeDay}
      />
    </>
  );
};

以下是选项卡:

const OITimeTabs = () => {
  const { t } = useTranslation();

  const [tabsValue, setTabsValue] = useState(0);
  const handleChange = (_, newValue) => {
    setTabsValue(newValue);
  };

  return (
    <>
      <Box sx={{ width: "100%", my: 2 }}>
        <StyledTabs
          onChange={handleChange}
          value={tabsValue}
          aria-label="Tabs to choose between whole day and time range delivery"
          TabIndicatorProps={{ hidden: true }}
        >
          <StyledTab
            label={t("orderIntake.timePicker.timeRange")}
            {...a11yProps(0)}
          />
          <StyledTab label={t("orderIntake.wholeDay")} {...a11yProps(1)} />
        </StyledTabs>
        <TimePickerOwn wholeDay={!!tabsValue} />
      </Box>
      <Typography sx={{ fontSize: "14px", color: "#00374d", mb: 1 }}>
        {`${t("orderIntake.timePicker.note")}: ${t(
          "orderIntake.timePicker.noteDescription",
          {
            from: "01:00 PM",
            to: "11:59 PM",
          }
        )}`}
      </Typography>
    </>
  );
};
reactjs react-hooks material-ui react-hook-form
1个回答
0
投票

也许只有在时间发生变化时才尝试更新savedTime状态。

// helper function
const hasTimeChanged = (savedTime, formTimeValues) => {
  return (
    savedTime.defaultEarliestLoadTime !== formTimeValues?.defaultEarliestLoadTime ||
    savedTime.defaultLatestLoadTime !== formTimeValues?.defaultLatestLoadTime
  );
};

useEffect(() => {
  if (wholeDay) {
    setSavedTime(formTimeValues);
    setValue("defaultDeliveryWindow", wholeDayRange.defaultDeliveryWindow);
  } else if (hasTimeChanged(savedTime, formTimeValues)) {
    setValue("defaultDeliveryWindow", savedTime);
  }
}, [setValue, wholeDay, savedTime, formTimeValues]);
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.