Heim  >  Fragen und Antworten  >  Hauptteil

React-Unterkomponenten können Zustandsänderungen von asynchronen Funktionen innerhalb von useEffect nicht erkennen

<p>Ich versuche, einen Status zu übergeben, der in einer asynchronen Funktion generiert wurde, die sich selbst in useState befindet. Ich habe gelernt, dass useRef wahrscheinlich der beste Weg ist, dieses Problem zu lösen, da es auf veränderbare Zustände verweisen kann, und habe dabei etwas über React-useStateRef erfahren, das schließlich ein weiteres Problem löste, bei dem der Zustand in meiner Hauptkomponente nie aktualisiert wurde. Problem (erhält ständig „ zu viele Renderfehler). Es fungiert also im Wesentlichen als useRef und useState in einem. </p> <p>Obwohl mein Status schließlich aktualisiert wurde, wurde er immer noch nicht an meine Canvas-Komponente übergeben. Ich versuche, das Blutzuckerdiagramm einer Leinwand basierend auf den aus einem Datensatz erhaltenen Temperaturen zu aktualisieren. </p> <pre class="brush:php;toolbar:false;">import { useEffect } from 'react'; importiere useState aus 'react-usestateref'; import { getServerData } from './serviceData'; „./App.css“ importieren Canvas aus „./components/Canvas“ importieren; Funktion App() { const [dataset, setDataset] = useState(null); const [units, setUnits] = useState('metric'); // Leinwand-Hintergrundgrafikmaterial var [currentBG, setCurrentBG, currentBGref] = useState(null); useEffect(() => { const fetchServerData = async () => const data = waiting getServerData(city, Units); setDataset(data); Funktion updateBG() { const Schwelle = Einheiten === „metrisch“ 20 : 60; if (data.temp <= Schwellenwert) { setCurrentBG('snow'); } anders { setCurrentBG('sunny'); } } updateBG(); } fetchServerData(); console.log(aktuelleBG) }, [Stadt, Einheiten, currentBGref.current, currentFGref.current]) const isCelsius = currentUnit === "C"; button.innerText = isCelsius ? "°F" : "°C"; setUnits(isCelsius ? "metric" : "imperial"); }; zurückkehren ( <div className="app"> { Datensatz && ( <Canvas width={640} height={480} currentBG={currentBGref.current}></Canvas> )} </div> ); } Standard-App exportieren;</pre> <p>Ich kann nur den Anfangswert übergeben und es wird nie darüber hinaus aktualisiert, obwohl das console.log in useEffect zeigt, dass es definitiv aktualisiert wird. Warum wird es also nicht an meine Komponente weitergeleitet? </p>
P粉609866533P粉609866533384 Tage vor462

Antworte allen(1)Ich werde antworten

  • P粉501007768

    P粉5010077682023-09-03 00:25:16

    useStateRef似乎是一种反模式。您决定新状态是什么,所以如果您需要另一个对它的引用,您总是可以自己创建一个。我建议尽量减少画布上的属性,以防止不必要的重新渲染。

    function App({ width, height }) {
      const canvas = React.useRef()
      const [color, setColor] = React.useState("white")
    
      // when color changes..
      React.useEffect(() => {
        if (canvas.current) {
          const context = canvas.current.getContext('2d');
          context.fillStyle = color
          context.fillRect(0, 0, width, height)
        }
      }, [color, width, height])
    
      return <div>
        <canvas ref={canvas} width={width} height={height} />
        <button onClick={_ => setColor("blue")} children="blue" />
        <button onClick={_ => setColor("green")} children="green" />
        <button onClick={_ => setColor("red")} children="red" />
      </div>
    }
    
    ReactDOM.createRoot(document.querySelector("#app")).render(<App width={200} height={150} />)
    canvas { display: block; border: 1px solid black; }
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <div id="app"></div>

    或者也许没有理由将颜色存储为状态。您可以自己创建setColor函数并将其附加为事件监听器 -

    function App({ width, height }) {
      const canvas = React.useRef()
      const setColor = color => event => {
        if (canvas.current) {
          const context = canvas.current.getContext('2d');
          context.fillStyle = color
          context.fillRect(0, 0, width, height)
        }
      }
      return <div>
        <canvas ref={canvas} width={width} height={height} />
        <button onClick={setColor("blue")} children="blue" />
        <button onClick={setColor("green")} children="green" />
        <button onClick={setColor("red")} children="red" />
      </div>
    }
    
    ReactDOM.createRoot(document.querySelector("#app")).render(<App width={200} height={150} />)
    canvas { display: block; border: 1px solid black; }
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <div id="app"></div>

    我还建议您查看SVG。我发现SVG的API与React模式更加契合,比Canvas API更好。每个的功能不同,但如果SVG适用于您的需求,那么值得考虑。

    Antwort
    0
  • StornierenAntwort