Entonces, me he topado con esta extraña situación:
Tengo un proveedor global de React Context, que proporciona un estado global, así
const Context = createContext(); const ContextProvider = ({children}) => { const [state, setState] = useState(''); return <Context.Provider value={{state, setState}}>{children}</Context.Provider> } const useMyState = () => { const {state, setState} = useContext(Context); return { state, setState } } const Component = () => { const {setState} = useMyState(); useEffect(() => { elementRef.addEventListener('click', () => { setState('someState'); }); return () => { elementRef.removeEventListener('click', () => null); } },[]) return <> // ... </> } eslint sugiere que mi setState debe agregarse a la matriz de dependencias de useEffect ,
useEffect(() => { elementRef.addEventListener('click', () => { setState('someState'); }); },[setState]) Supongo que esto podría estar relacionado de alguna manera con la desestructuración del contexto dentro del archivo useMyState.ts
pero eso se siente un poco raro y poco intuitivo...
mi pregunta es ¿realmente se requiere setState dentro de la matriz de dependencia? y si es así, ¿por qué?
mi pregunta es ¿realmente se requiere
setStatedentro de la matriz de dependencia?
No, no lo es, pero ESLint no lo sabe, porque no tiene forma de saber que el miembro setState del objeto de contexto que está usando es estable. Lo sabe (porque useState garantiza que el setter sea estable, y lo está pasando textualmente a través del contexto y su gancho useMyState ), pero ESLint no lo sabe.
Puede agregarlo como una dependencia para hacer feliz a ESLint (no hará ninguna diferencia si ya está proporcionando una matriz, porque el setter nunca cambia; vea a continuación si no está proporcionando una matriz), o puede poner en un comentario para decirle a ESLint que omita la verificación de ese código, o puede desactivar la regla (pero es muy fácil pasar por alto las dependencias, así que tenga cuidado si lo hace).
(Si no está proporcionando una matriz [porque desea que el efecto se ejecute después de cada procesamiento], agregar una matriz con el setter evitará que eso suceda, por lo que querrá optar por la opción de deshabilitar el ESLint error para esa situación. O hay soluciones desagradables como usar una referencia con un valor numérico cada vez mayor. :-))
Sin embargo, hay un problema con ese código. Está agregando repetidamente nuevos detectores de eventos al elemento sin siquiera eliminarlos, porque sin una matriz de dependencia, la devolución de llamada useEffect se llama cada vez que se procesa el componente, y está creando una nueva función de controlador de eventos cada vez, por lo que se acumularán .
Por lo tanto, deberá hacer que elementRef.current sea una dependencia y necesitará una devolución de llamada de limpieza:
const Component = () => { const {setState} = useMyState(); useEffect(() => { const handler = () => { setState("someState"); }; const element = elementRef.current; // Note −−−−−−−−−−−−−−−−−−^^^^^^^^ element.addEventListener("click", handler); return () => { element.removeEventListener("click", handler); }; }, [elementRef.current]); // <== Optionally add `setState` to this return <> // ... </>; };