我有一个用作时间选择器的组件。我还使用 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>
</>
);
};
也许只有在时间发生变化时才尝试更新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]);