为什么 useEffect React Hook 不能正常使用依赖项?
Why does useEffect React Hook not work properly with dependency?
我正在 React Web App 和 Fullcalendar
一起工作。 我认为不需要知道 Fullcalendar 就可以回答这个问题。这更像是对 React 理解的问题。
长话短说,Fullcalendar
有一个 api 从给定的 source
重新获取任何 events
。
就我而言,我的 source
是 state.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>)
;
现在,如您所见,只要我没有 calendar
的 reference
,我就无法启动 calendarApi
。只要我没有 api,我就不能 refetch
。
我不得不提一下,当我去掉 useEffect
依赖项 (state
) 时,我不再面临获取事件的问题(即使是在初始渲染时)。但是,这会导致我的代码中出现其他我无法修复的问题,因此我宁愿使用 useEffect
.
来修复它
更新
有人要求更深入地解释代码中发生的事情。
Fullcalendar
需要 source
个 events
(日历任务)。要提供此 source
,必须在渲染之前启动它,我在 useEffect
中正在这样做
检查 reference
到 element Fullcalendar
是否已经存在以防止渲染错误
if (calendarRef.current !== undefined) {//...}
正在检查是否已添加 source
。如果否,则使用 Fullcalendar's
api 启动 source
。 .addEventSource
添加一个包含 array
的 objects
(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
。
这可能对以后遇到 React
和 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 (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
)
我正在 React Web App 和 Fullcalendar
一起工作。 我认为不需要知道 Fullcalendar 就可以回答这个问题。这更像是对 React 理解的问题。
长话短说,Fullcalendar
有一个 api 从给定的 source
重新获取任何 events
。
就我而言,我的 source
是 state.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>)
;
现在,如您所见,只要我没有 calendar
的 reference
,我就无法启动 calendarApi
。只要我没有 api,我就不能 refetch
。
我不得不提一下,当我去掉 useEffect
依赖项 (state
) 时,我不再面临获取事件的问题(即使是在初始渲染时)。但是,这会导致我的代码中出现其他我无法修复的问题,因此我宁愿使用 useEffect
.
更新
有人要求更深入地解释代码中发生的事情。
Fullcalendar
需要 source
个 events
(日历任务)。要提供此 source
,必须在渲染之前启动它,我在 useEffect
检查 reference
到 element Fullcalendar
是否已经存在以防止渲染错误
if (calendarRef.current !== undefined) {//...}
正在检查是否已添加 source
。如果否,则使用 Fullcalendar's
api 启动 source
。 .addEventSource
添加一个包含 array
的 objects
(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
。
这可能对以后遇到 React
和 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 (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
)