Rumah  >  Soal Jawab  >  teks badan

Tatasusunan diluluskan sebagai prop tidak mencerminkan perubahan

Soalan ini lebih kepada mengetahui lebih lanjut tentang cara tindak balas mengendalikan dan bertindak balas terhadap perubahan dan bukannya pelaksanaan, jadi saya biarkan pendekatan-props-immutable berkembang sedikit.

Saya cuba mendapatkan elemen pertama tatasusunan dan mengeluarkannya daripada tatasusunan asal yang dihantar kepada komponen sebagai prop:

const ChildComponent = (
  arrayToChange: Array<any>[]
) => {
  const elementFromArray = arrayToChange.shift();
}

Dari definisi kaedah shift()::

Kaedah

shift() mengalih keluar elemen pertama daripada tatasusunan dan mengembalikan elemen yang dialih keluar. Kaedah ini mengubah panjang tatasusunan.

Walaupun pembolehubah elementFromArray kini mengandungi elemen dalam tatasusunan, tatasusunan sudah lengkap, ia tidak terjejas dalam apa jua cara dan masih mengandungi semua elemen.

Tetapi bagaimana ini boleh berlaku? React harus melepasi prop melalui rujukan, jadi tatasusunan asal harus terjejas. Saya akan faham jika React meletakkan beberapa perlindungan dan perubahan itu tidak akan ditunjukkan pada ibu bapa, namun, saya masih mahu perubahan itu ditunjukkan pada kanak-kanak itu. Saya tidak dapat mencari apa-apa yang berguna untuk menerangkan tingkah laku ini, kebanyakan sumber hanya menyebut kaedah tidak berubah untuk prop dan cara mencari penyelesaian, tetapi bukan sebab atau logik di sebaliknya.

Walaupun pembolehubah elementFromArray kini mengandungi elemen dalam tatasusunan, tatasusunan itu lengkap, ia tidak terjejas dalam apa jua cara dan masih mengandungi semua elemen. Walau bagaimanapun, jika saya menggunakan kaedah Push(), perubahan dicerminkan dan arrayToChange mengandungi satu lagi elemen.

Soalan saya ialah - mengapa arrayToChange bertindak balas secara berbeza terhadap kaedah ini? Jika shift() tidak mengubah kandungan, saya harap push() juga tidak.

P粉685757239P粉685757239381 hari yang lalu480

membalas semua(2)saya akan balas

  • P粉182218860

    P粉1822188602023-09-07 14:26:37

    function Parent() {
      const forceUpdate = useForceUpdate();
      const [letters] = React.useState(["a", "b", "c"]);
    
      return (
        <div className="bg-yellow">
          A: {JSON.stringify(letters)}
          <ChildShowArray array={letters} />
          B: {JSON.stringify(letters)}
          <ChildChangeArray arrayToChange={letters} />
          C: {JSON.stringify(letters)}
          <ChildShowArray array={letters} />
          D: {JSON.stringify(letters)}
    
          <hr />
          <button type="button" onClick={forceUpdate}>re-render</button>
        </div>
      );
    }
    
    function ChildChangeArray({ arrayToChange }) {
      const elementFromArray = arrayToChange.shift();
      
      return (
        <div className="bg-red">
          elementFromArray = {JSON.stringify(elementFromArray)}
        </div>
      );
    }
    
    function ChildShowArray({ array }) {
      return (
        <div className="bg-green">
          array = {JSON.stringify(array)}
        </div>
      );
    }
    
    // helper hook
    function useForceUpdate() {
      const [_state, setState] = React.useState({});
      return React.useCallback(() => { setState({}) }, []);
    }
    
    ReactDOM.createRoot(document.querySelector("#root")).render(<Parent />)
    .bg-yellow { background: yellow }
    .bg-red { background: red }
    .bg-green { background: green }
    <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="root"></div>

    Tingkah laku dalam coretan kod boleh dijelaskan jika anda menganggap proses pemaparan sebagai algoritma yang mengutamakan keluasan.

    JSX akan menukar:

    <div className="bg-yellow">
      A: {JSON.stringify(letters)}
      <ChildShowArray array={letters} />
      B: {JSON.stringify(letters)}
      <ChildChangeArray arrayToChange={letters} />
      C: {JSON.stringify(letters)}
      <ChildShowArray array={letters} />
      D: {JSON.stringify(letters)}
    </div>

    Masukkan JavaScript berikut:

    React.createElement("div", { className: "bg-yellow" },
      "A: ", JSON.stringify(letters),
      React.createElement(ChildShowArray, { array: letters }),
      "B: ", JSON.stringify(letters),
      React.createElement(ChildChangeArray, { arrayToChange: letters }),
      "C: ", JSON.stringify(letters),
      React.createElement(ChildShowArray, { array: letters }),
      "D: ", JSON.stringify(letters),
    )
    

    React.createElement(ChildShowArray, { array: letter }) 创建一个不会立即调用 ChildShowArray Struktur komponen. Ia akan mencipta beberapa jenis struktur/objek perantaraan yang hanya akan dijalankan apabila pemapar memintanya.

    Letakkannya dalam {...} (JSX 上下文)中的 JavaScript 直接作为参数传递,因此直接解析。这意味着 Parent 中的所有 {JSON.stringify(letters)} untuk dijalankan sebelum sebarang kod dalam komponen anak dijalankan.

    Apabila membina struktur induk selesai, pemapar akan mengakses setiap struktur/objek perantaraan dan memintanya untuk membuat. Ini dilakukan dari atas ke bawah, itulah sebabnya pemaparan ChildShowArray 渲染仍然显示完整数组的原因。然后渲染 ChildChangeArray 并删除第一个元素。第二个 ChildShowArray pertama mencerminkan perubahan ini dan dipaparkan tanpa elemen pertama.

    Sila ambil perhatian, shift() 确实会更改 letters 的内容,但是当调用它时,Parent 的内容已经呈现并且不再变化。此更改确实会影响下一次渲染的Parent (klik butang "Rerender" dalam coretan). Ia juga mempengaruhi pemaparan komponen anak lain di bawahnya yang menggunakan rujukan tatasusunan yang sama.

    balas
    0
  • P粉287726308

    P粉2877263082023-09-07 00:57:49

    Saya tidak pasti sepenuhnya apa soalannya, tetapi saya akan meneka di sini, jadi sila tinggalkan komen di sini dan saya akan menukarnya sebelum mengundi.

    Saya rasa anda patut mencuba ini dalam komponen anak anda:

    const [data, setData] = React.useState(arrayToChange);
    
    React.useEffect(() => setData(arrayToChange), [arrayToChange.length]);

    Kemudian gunakan "data" untuk memetakan ke output dalam jsx

    Kemudian dalam komponen induk, alihkan arrayToChange. Anda boleh menganggap useEffect sebagai "pemerhati" yang akan menyala apabila panjang tatasusunan berubah.

    balas
    0
  • Batalbalas