TextField Re-renders ที่ไม่จำเป็น
ฉันสังเกตเห็นปัญหาที่ทุกส่วนประกอบภายในพาเรนต์เดียวกัน ( แอพในตัวอย่างด้านล่าง) จะแสดงผลเมื่อสถานะ / อุปกรณ์ประกอบฉากที่ไม่เกี่ยวข้องเปลี่ยนไปทำให้หน้า / ฟอร์มช้าลงอย่างเห็นได้ชัด
ฉันทำตามคำแนะนำมากมายเช่นการช่วยจำตัวจัดการเหตุการณ์และอุปกรณ์ประกอบฉาก แต่ส่วนประกอบที่ไม่เกี่ยวข้องยังคงแสดงผลอีกครั้ง ฉันนิ่งงัน ฉันไม่เข้าใจอะไรเกี่ยวกับ 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>
</>
);
}
คำตอบ
เครื่องมือดีบักเกอร์ถูกบั๊กเกี่ยวกับคอมโพเนนต์ที่บันทึกไว้ เมื่อคุณบันทึกส่วนประกอบพวกเขาจะไม่แสดงซ้ำจริง ๆ แต่เครื่องมือดีบั๊กจะไฮไลต์องค์ประกอบเหล่านั้นอยู่ดี (ดู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เนื่องจากการบันทึกช่วยจำ