GOOGLE ADS

Freitag, 29. April 2022

„useViewBox“-Hook reagieren, wenn die SVG-ViewBox die ESLint-Regel „erschöpfend deps“ nicht erfüllt

Ich versuche, einen praktischen Reaktionshaken zu erstellen, um ein SVG viewBoxan seinen Inhalt anzupassen.

import { useState } from 'react';
import { useEffect } from 'react';
import { useRef } from 'react';
// get fitted view box of svg
export const useViewBox = () => {
const svg = useRef();
const [viewBox, setViewBox] = useState(undefined);
useEffect(() => {
// if svg not mounted yet, exit
if (!svg.current)
return;
// get bbox of content in svg
const { x, y, width, height } = svg.current.getBBox();
// set view box to bbox, essentially fitting view to content
setViewBox([x, y, width, height].join(' '));
});
return [svg, viewBox];
};

dann benutze es:

const [svg, viewBox] = useViewBox();
return <svg ref={svg} viewBox={viewBox}>... content...</svg>

Aber ich bekomme den folgenden Eslint-Fehler:

React Hook useEffect contains a call to 'setViewBox'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass [viewBox] as a second argument to the useEffect Hook.eslint(react-hooks/exhaustive-deps)

Ich bin bis jetzt noch nie auf eine Situation gestoßen, in der die React-Hooks-Eslint-Fehler "falsch" waren. Ich habe das Gefühl, dass dies eine vollkommen legitime Verwendung von Hooks ist. Es muss als Effekt ausgeführt werden, da es NACH dem Rendern ausgeführt werden muss, um festzustellen, ob sich der Inhalt der SVG geändert hat. Und was die Warnmeldung angeht: Dieser Code vermeidet bereits eine unendliche Renderschleife, da setState kein erneutes Rendern auslöst, es sei denn, der neue Wert unterscheidet sich vom aktuellen.

Ich kann die Eslint-Regel deaktivieren:

// eslint-disable-next-line react-hooks/exhaustive-deps

Aber das scheint falsch zu sein, und ich frage mich, ob es einen einfacheren/anderen Weg gibt, dasselbe Ziel zu erreichen, das ich nicht sehe.

Ich könnte den Aufrufer von useViewBoxeine Variable bereitstellen lassen, die in useEffectdas Abhängigkeitsarray von einfügt und ein erneutes Rendern erzwingt, aber ich möchte, dass es flexibler und einfacher zu verwenden ist.

Oder vielleicht liegt das Problem tatsächlich in der exhaustive-depsRegel. Vielleicht sollte es setStateinnerhalb einer no-dependencies-specified zulassen, useEffectwenn es eine Bedingung vor dem erkennt setState...


Lösung des Problems

Okay, ich habe eine "Lösung" gefunden, inspiriert von dieser Antwort. Ich denke, es ist eine Art dumme Arbeit, aber ich nehme an, es ist besser, als die Eslint-Regel zu deaktivieren:

import { useState } from 'react';
import { useEffect } from 'react';
import { useRef } from 'react';
import { useCallback } from 'react';
// get fitted view box of svg
export const useViewBox = () => {
const svg = useRef();
const [viewBox, setViewBox] = useState(undefined);
const getViewBox = useCallback(() => {
// if svg not mounted yet, exit
if (!svg.current)
return;
// get bbox of content in svg
const { x, y, width, height } = svg.current.getBBox();
// set view box to bbox, essentially fitting view to content
setViewBox([x, y, width, height].join(' '));
}, []);
useEffect(() => {
getViewBox();
});
return [svg, viewBox];
};

Keine Kommentare:

Kommentar veröffentlichen

Warum werden SCHED_FIFO-Threads derselben physischen CPU zugewiesen, obwohl CPUs im Leerlauf verfügbar sind?

Lösung des Problems Wenn ich das richtig verstehe, versuchen Sie, SCHED_FIFO mit aktiviertem Hyperthreading ("HT") zu verwenden, ...