为了更好地理解React中的Context API,我创建了以下示例Context:
import * as React from "react";
import {useEffect, useReducer, useState} from "react";
class State {
private v1: number;
private v2: number;
constructor(v1: number, v2: number) {
this.v1 = v1;
this.v2 = v2;
}
static zero(): State {
return new State(0, 0);
}
bumpV1(): State {
return new State(this.v1 + 1, this.v2);
}
bumpV2(): State {
return new State(this.v1, this.v2 + 1);
}
getV1(): number {
return this.v1;
}
getV2(): number {
return this.v2;
}
}
type Action = { type: 'v1' | 'v2' | 'toggle_timer' | 'reset'};
type ContextValueType = {
state: State,
dispatch: React.Dispatch<Action>
}
const ContextExample: React.Context<ContextValueType> = React.createContext({} as ContextValueType);
function ContextProvider(props: { children: JSX.Element}): JSX.Element {
const [interval, updateInterval] = useState(undefined as (NodeJS.Timeout | undefined));
const reducer: React.Reducer<State, Action> = (prev: State, action: Action) => {
switch (action.type) {
case 'v1':
return prev.bumpV1();
case 'v2':
return prev.bumpV2();
case 'toggle_timer':
toggleTimer();
return prev;
case 'reset':
clearTimer();
return State.zero();
}
};
const [state, dispatch] = useReducer(reducer, State.zero());
function toggleTimer() {
if (interval) {
clearInterval(interval);
updateInterval(undefined);
} else {
const ret = setInterval(() => {
dispatch({ type: 'v1' })
}, 1000);
updateInterval(ret);
}
}
function clearTimer() {
if (interval) {
toggleTimer();
}
}
useEffect(() => {
toggleTimer();
return clearTimer;
}, []);
const value = { state, dispatch };
return <ContextExample.Provider value={value}>{props.children}</ContextExample.Provider>
}
export {ContextExample, ContextProvider};
在这里,我有一个使用toggleTimer()
函数启动和停止的计时器,我希望既可以从调度程序中也可以从提供程序本身进行调用(因为我想启动计时器)加载)。
这导致React响应以下警告:
./src/ContextExample.tsx
Line 74:8: React Hook useEffect has missing dependencies: 'clearTimer' and 'toggleTimer'. Either include them or remove the dependency array react-hooks/exhaustive-deps
通读https://github.com/facebook/create-react-app/issues/6880,我不确定最好的方法是添加// eslint-disable-next-line react-hooks/exhaustive-deps
还是以其他方式重组我的代码。