我正在尝试构建一个分析仪表板,允许用户过滤项目、toDate、fromDate、timeFrame。并且还允许他们清除过滤器
根据 toDate 和 fromDate 之间的范围,TimeFrame 将被禁用。
useEffect(() => {
// fetch data only once when any of those dependencies changes
// or multiple of them changes at the same time.
// fetchData();
// setItInTheContext();
renderCount.current = renderCount.current + 1;
console.log("API called", `${renderCount.current}`);
}, [project, fromDate, toDate, timeFrame]);
我只想在这些依赖项中的任何一个发生变化或同时发生多个变化时获取数据一次。
我面临的问题是 JS 的延迟响应和异步行为,(请参阅 img。)由于在后端按天对数据进行分组需要比数周更多的时间,所以我最终获取按天分组的数据并将其设置到上下文中。即使该日期范围内禁用了天数。
以下 codeSandbox 模拟了这个问题。请检查沙盒控制台。 CODE_SANDBOX_链接:https://codesandbox.io/s/elated-glade-zbzmyv
我还尝试将所有依赖项放在一个 filterObject 中,但行为完全相同。 https://codesandbox.io/s/gracious-lehmann-4ftsqi
我也尝试过这种方法,但是有很多场景需要考虑。 (很多如果的---可能不是一个好方法---)
以下文件与codesandbox相同。(如果您已经签出sandbox链接,请忽略)
// ProjectContext.js
import { createContext, useMemo, useState, useContext } from "react";
const ProjectContext = createContext(null);
export const ProjectProvider = ({ children }) => {
const [project, setProject] = useState("P1");
const date = new Date();
const [fromDate, setFromDate] = useState(
new Date(date.getFullYear(), date.getMonth(), 1)
);
const [toDate, setToDate] = useState(
new Date(date.getFullYear(), date.getMonth() + 1, 0)
);
const [timeFrame, setTimeFrame] = useState("years");
const value = useMemo(
() => ({project, setProject, fromDate, setFromDate, toDate, setToDate, timeFrame, setTimeFrame
}), [ project, setProject, fromDate, setFromDate, toDate, setToDate, timeFrame, setTimeFrame]
);
return (
<ProjectContext.Provider value={value}>{children}</ProjectContext.Provider>
);
};
export const useProject = () => {
const context = useContext(ProjectContext);
if (!context) {
throw new Error("ProjectContext must be used within ProjectProvider");
}
return context;
};
// 应用程序.js
import "./styles.css";
import { useEffect, useRef } from "react";
import { useProject } from "./ProjectContext";
export default function App() {
const { toDate, fromDate, project, timeFrame, setTimeFrame, setFromDate, setToDate, setProject } = useProject();
const renderCount = useRef(0);
useEffect(() => {
// fetch data only once when any of the following dependencies changes
// or multiple of them changes at the same time.
// fetchData();
// setItInTheContext()
renderCount.current = renderCount.current + 1;
console.log("API called", `${renderCount.current}`);
}, [project, fromDate, toDate, timeFrame]);
useEffect(() => {
setTimeFrame(`days ${renderCount.current}`);
}, [toDate, fromDate]);
const getStringDate = (date) => {
return new Date(date).toDateString();
};
return (
<div>
<input
type="submit"
onClick={(e) => setProject(`Project ${renderCount.current}`)}
label="Hello"
value="Select Project"
/>
<input
type="date"
value={fromDate}
onChange={(e) => setFromDate(e.target.value)}
placeholder="Enter from date"
/>
<input
type="date"
value={toDate}
onChange={(e) => setToDate(e.target.value)}
placeholder="Enter to date"
/>
<input
type="submit"
value="Change timeFrame"
onClick={() => {
setTimeFrame(`weeks ${renderCount.current}`);
}}
/>
<input
type="submit"
value="Clear Filter"
onClick={() => {
setFromDate(new Date());
setToDate(new Date());
}}
/>
<p>Render Count : {renderCount.current}</p>
<p>Project : {project}</p>
<p>To Date : {getStringDate(toDate)}</p>
<p>From Date :{getStringDate(fromDate)}</p>
<p>TimeFrame : {timeFrame}</p>
</div>
);
}
提前谢谢你...!