为什么 useEffect React Hook 不能正常使用依赖项?

Why does useEffect React Hook not work properly with dependency?

我正在 React Web AppFullcalendar 一起工作。 我认为不需要知道 Fullcalendar 就可以回答这个问题。这更像是对 React 理解的问题。

长话短说,Fullcalendar 有一个 api 从给定的 source 重新获取任何 events。 就我而言,我的 sourcestate.events,以 useState 开头。当我的 state 改变时,我只想 refetch。到目前为止一切都很好。但是,在第一次初始渲染时,Fullcalendar 无法获取任何内容。

const OverviewPage: React.FunctionComponent<IOverviewPageProps> = (props) => {
    const calendarRef = useRef<any>();
    const [sourceAPI, setSourceAPI] = useState<any>(undefined);
    const [state, setState] = useState<State>({
        externalEvents: [],
        events: []
    });
   
useEffect(() => {
         if (calendarRef.current !== undefined) {
            let calendarApi = calendarRef.current.getApi();

            if (sourceAPI === undefined) {
                const source = calendarApi.addEventSource(state.events);
                source.refetch()
                setSourceAPI(source);
            } else {
                sourceAPI.refetch();
            }
        }
    }, [state])
return (<div>
           <FullCalendar
               ref={calendarRef}
               //other props
           />
        </div>)
;

现在,如您所见,只要我没有 calendarreference,我就无法启动 calendarApi。只要我没有 api,我就不能 refetch。 我不得不提一下,当我去掉 useEffect 依赖项 (state) 时,我不再面临获取事件的问题(即使是在初始渲染时)。但是,这会导致我的代码中出现其他我无法修复的问题,因此我宁愿使用 useEffect.

来修复它

更新

有人要求更深入地解释代码中发生的事情。 Fullcalendar 需要 sourceevents(日历任务)。要提供此 source,必须在渲染之前启动它,我在 useEffect

中正在这样做

检查 referenceelement Fullcalendar 是否已经存在以防止渲染错误

if (calendarRef.current !== undefined) {//...}

正在检查是否已添加 source。如果否,则使用 Fullcalendar's api 启动 source.addEventSource 添加一个包含 arrayobjects (events) 的来源 - 在本例中为 state.events - 和 returns 一个 Fullcalendar Source 以便我稍后可以与之交互(例如 refetch)。 .refetch() 只是获取 source 的内容并(重新)在日历上呈现它们(换句话说就是 state.events 的内容)。 然后我将这个 Fullcalendar Source 存储在 React State 中,这样我以后可以再次与同一个源交互,而不必再次重新启动它。

 if (sourceAPI === undefined) {
                const source = calendarApi.addEventSource(state.events);
                source.refetch()
                setSourceAPI(source);
            }

如果 Fullcalendar Source 已经存在,请再次应用 refetch 调用。

else {
        sourceAPI.refetch();
}

Fullcalendar真的不用多说了。我怀疑 React State management 中的问题并且我在那里做错了(useEffect)。

在尝试了多种不同的方法后,我终于设法让 Fullcalendar 在第一次初始渲染时也渲染了 events。 这可能对以后遇到 ReactFullcalendar

的人有帮助
const OverviewPage: React.FunctionComponent<IOverviewPageProps> = (props) => {
    const calendarRef = useRef<any>();
    const [sourceAPI, setSourceAPI] = useState<any>(undefined);
    const [state, setState] = useState<State>({
        externalEvents: [],
        events: []
    });
useEffect(() => {
        if (sourceAPI === undefined && calendarRef.current !== undefined) {
            const calendarApi = calendarRef.current.getApi();
            const source = calendarApi.addEventSource(state.events);
            setSourceAPI(source);
        }
    });
   
useEffect(() => {
        if (sourceAPI !== undefined) {
            sourceAPI.refetch();
        }
    }, [state]);

return (<div>
           <FullCalendar
               ref={calendarRef}
               //other props
           />
        </div>)
;

注意第一个useEffect每次都会触发,而第二个只有在dependency发生变化时才会触发。这样,肯定会启动 source,这似乎是原始代码的主要问题(calendarRef.current 在初始 start/render 上总是 undefined