Работая, чтобы лучше понять API контекста в React, я создал следующий пример контекста:
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
или иначе реструктурировать мой код.