TextField Re-renders ที่ไม่จำเป็น

Nov 06 2020

ฉันสังเกตเห็นปัญหาที่ทุกส่วนประกอบภายในพาเรนต์เดียวกัน ( แอพในตัวอย่างด้านล่าง) จะแสดงผลเมื่อสถานะ / อุปกรณ์ประกอบฉากที่ไม่เกี่ยวข้องเปลี่ยนไปทำให้หน้า / ฟอร์มช้าลงอย่างเห็นได้ชัด

ฉันทำตามคำแนะนำมากมายเช่นการช่วยจำตัวจัดการเหตุการณ์และอุปกรณ์ประกอบฉาก แต่ส่วนประกอบที่ไม่เกี่ยวข้องยังคงแสดงผลอีกครั้ง ฉันนิ่งงัน ฉันไม่เข้าใจอะไรเกี่ยวกับ React

[ CodeSandbox ] ใน React debugger ให้เปิดใช้งาน: เน้นการอัปเดตเมื่อคอมโพเนนต์แสดงผล

import React, { useMemo, useState } from "react";
import { TextField } from "@material-ui/core";

function MyTextInput(props) {
  return (
    <TextField
      variant={"outlined"}
      onChange={props.onChange}
      value={props.value}
    />
  );
}

export default function App() {
  const [exampleTextValue1, setExampleTextValue1] = useState("");
  const [exampleTextValue2, setExampleTextValue2] = useState("");

  const handleChange1 = useMemo(
    () => (event) => setExampleTextValue1(event.target.value),
    []
  );

  const handleChange2 = useMemo(
    () => (event) => setExampleTextValue2(event.target.value),
    []
  );

  return (
    <>
      <div>
        Change me:
        <MyTextInput value={exampleTextValue1} onChange={handleChange1} />
      </div>

      <div>
        Unrelated inputs. Should not re-render:
        <MyTextInput value={exampleTextValue2} onChange={handleChange2} />
        <MyTextInput value={exampleTextValue2} onChange={handleChange2} />
        {/*  to feel the impact, copy the above line like 98 more times  */}
      </div>
    </>
  );
}

คำตอบ

1 Jayce444 Nov 06 2020 at 06:52

เครื่องมือดีบักเกอร์ถูกบั๊กเกี่ยวกับคอมโพเนนต์ที่บันทึกไว้ เมื่อคุณบันทึกส่วนประกอบพวกเขาจะไม่แสดงซ้ำจริง ๆ แต่เครื่องมือดีบั๊กจะไฮไลต์องค์ประกอบเหล่านั้นอยู่ดี (ดูhttps://github.com/facebook/react/issues/19778).

ในการทดสอบการเรนเดอร์จริงให้เปลี่ยนค่าสถานะเริ่มต้นสำหรับอินพุตที่สอง (ซึ่งแสดงผลหลายครั้ง) เป็นบางอย่างเช่น "ทดสอบ" จากนั้นใส่ส่วนประกอบที่บันทึกconsole.logไว้ภายในMyTextInputเพื่อดูว่ากำลังได้รับการแสดงผลใหม่:

const MyTextInput = React.memo((props) => {
  console.log(props.value);
  return (
    <TextField
      variant={"outlined"}
      onChange={props.onChange}
      value={props.value}
      disabled={props.disabled}
    />
  );
});

คุณจะเห็นว่ามันพิมพ์ค่า "test" หนึ่งครั้งสำหรับอินพุตที่สองทั้งหมดเมื่อแสดงผลครั้งแรกจากนั้นเมื่อคุณพิมพ์ครั้งแรกมันจะไม่บันทึกอินพุตที่สองทั้งหมดconsole.logเนื่องจากการบันทึกช่วยจำ