cari

Rumah  >  Soal Jawab  >  teks badan

Subkomponen bertindak balas tidak dapat merasakan perubahan keadaan daripada fungsi tak segerak di dalam useEffect

<p>Saya cuba menghantar keadaan yang dijana dalam fungsi async, yang dengan sendirinya berada di dalam useState. Saya mengetahui bahawa useRef mungkin merupakan cara terbaik untuk menyelesaikan masalah ini kerana ia boleh merujuk keadaan boleh ubah, dan dalam proses belajar tentang React-useStateRef, yang akhirnya menyelesaikan masalah lain di mana keadaan di dalam komponen utama saya tidak pernah dikemas kini Masalah (terus mendapat " terlalu banyak render" ralat). Jadi ia pada asasnya bertindak sebagai useRef dan useState digabungkan menjadi satu. </p> <p>Walau bagaimanapun, walaupun keadaan saya akhirnya dikemas kini, ia masih tidak dihantar kepada komponen Kanvas saya. Saya cuba mengemas kini graf BG kanvas berdasarkan suhu yang diperoleh daripada set data. </p> <pre class="brush:php;toolbar:false;">import { useEffect } daripada 'react'; import useState daripada 'react-usestateref'; import { getServerData } daripada './serviceData'; import "./App.css" import Kanvas daripada './components/Canvas'; fungsi Apl() { const [set data, setDataset] = useState(null); const [unit, setUnit] = useState('metrik'); // bahan grafik latar belakang kanvas var [currentBG, setCurrentBG, currentBGref] = useState(null); useEffect(() => { const fetchServerData = async () => data const = menunggu getServerData(bandar, unit); setDataset(data); fungsi kemas kiniBG() { ambang const = unit === "metrik" 20 : 60; jika (data.temp <= ambang) { setCurrentBG('salji'); } lain { setCurrentBG('cerah'); } } kemas kiniBG(); } fetchServerData(); console.log(currentBG) }, [bandar, unit, currentBGref.current, currentFGref.current]) const isCelsius = currentUnit === "C"; button.innerText = isCelsius ? setUnit(isCelsius ? "metric" : "imperial"); }; kembali ( <div className="app"> { set data && ( <Lebar kanvas={640} tinggi={480} semasaBG={currentBGref.current}></Canvas> )} </div> ); } eksport Apl lalai;</pre> <p>Saya hanya boleh melepasi nilai awal dan ia tidak pernah mengemas kini melepasi itu, walaupun console.log inside useEffect menunjukkan bahawa ia pasti sedang mengemas kini. Jadi mengapa ia tidak dihantar kepada komponen saya? </p>
P粉609866533P粉609866533438 hari yang lalu494

membalas semua(1)saya akan balas

  • P粉501007768

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

    useStateRef nampaknya anti-corak. Anda memutuskan keadaan baharu itu, jadi jika anda memerlukan rujukan lain kepadanya, anda sentiasa boleh menciptanya sendiri. Saya mengesyorkan meminimumkan sifat pada kanvas untuk mengelakkan pemaparan semula yang tidak perlu.

    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>

    Atau mungkin tiada sebab untuk menyimpan warna sebagai keadaan. Anda boleh mencipta sendiri fungsi setColor dan melampirkannya sebagai pendengar acara -

    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>

    Saya juga mengesyorkan anda menyemak SVG. Saya mendapati bahawa API SVG lebih sesuai dengan corak React daripada API Kanvas. Keupayaan setiap satu adalah berbeza, tetapi jika SVG berfungsi untuk keperluan anda, ia patut dipertimbangkan.

    balas
    0
  • Batalbalas