React with useCallback and useMemo의 재렌더 문제
나는 각각 다른 id(Speaker.js)를 가진 세 가지 구성요소를 렌더링하는 구성요소(Hello.js)의 꽤 간단한 예를 가지고 있다.나는 a를 가지고 있다.clickFunction
내가 의장에게서 돌아갔다는 것을.React.memo와 React.useCallback을 사용하면 단 한 가지만 변경될 때 세 가지 모두 다시 렌더링하는 것을 막을 수 있다고 생각하지만, 안타깝게도 스피커의 콘솔.log에서 볼 수 있으며, 세 가지 버튼 중 하나를 클릭하면 세 가지 버튼이 모두 렌더링된다.
스택블리츠의 문제 예는 다음과 같다.
https://stackblitz.com/edit/react-dmclqm
여보세요.js
import React, { useCallback, useState } from "react";
import Speaker from "./Speaker";
export default () => {
const speakersArray = [
{ name: "Crockford", id: 101, favorite: true },
{ name: "Gupta", id: 102, favorite: false },
{ name: "Ailes", id: 103, favorite: true },
];
const [speakers, setSpeakers] = useState(speakersArray);
const clickFunction = useCallback((speakerIdClicked) => {
var speakersArrayUpdated = speakers.map((rec) => {
if (rec.id === speakerIdClicked) {
rec.favorite = !rec.favorite;
}
return rec;
});
setSpeakers(speakersArrayUpdated);
},[speakers]);
return (
<div>
{speakers.map((rec) => {
return (
<Speaker
speaker={rec}
key={rec.id}
clickFunction={clickFunction}
></Speaker>
);
})}
</div>
);
};
스피커.js
import React from "react";
export default React.memo(({ speaker, clickFunction }) => {
console.log(`speaker ${speaker.id} ${speaker.name} ${speaker.favorite}`);
return (
<button
onClick={() => {
clickFunction(speaker.id);
}}
>
{speaker.name} {speaker.id} {speaker.favorite === true ? "true" : "false"}
</button>
);
});
왜냐하면 발사할 때clickFunction
이 기능을 다시 생성하기 위해 제거해야 하는 스피커를 업데이트한다.speakers
로부터clickFunction
종속성 및 액세스setState
콜백여기서 해결책:
가져오기 리액션, { useCallback, useState, useEffect }
import Speaker from "./Speaker";
export default () => {
const [speakers, setSpeakers] = useState([
{ name: "Crockford", id: 101, favorite: true },
{ name: "Gupta", id: 102, favorite: false },
{ name: "Ailes", id: 103, favorite: true },
]);
const clickFunction = useCallback((speakerIdClicked) => {
setSpeakers(currentState=>currentState.map((rec) => {
if (rec.id === speakerIdClicked) {
rec.favorite = !rec.favorite;
return {...rec};
}
return rec
}));
},[]);
useEffect(()=>{
console.log("render")
})
return (
<div>
{speakers.map((rec) => {
return (
<Speaker
speaker={rec}
key={rec.id}
clickFunction={clickFunction}
></Speaker>
);
})}
</div>
);
};
및 스피커 구성 요소의 경우:
import React from "react";
export default React.memo(({ speaker, clickFunction }) => {
return (
<button
onClick={() => {
clickFunction(speaker.id);
}}
>
{speaker.name} {speaker.id} {speaker.favorite === true ? "true" : "false"}
</button>
);
});
더 깊이 생각해 보면, 내 대답이 완전히 옳은 것은 아닐지도 모른다.[speakers]
의존은 의도한 대로 되지 않을 거야
두 가지:
그[speakers]
에게 전해진 의존.useCallback
함수가 매번 재생성되도록 함speakers
콜백 자체가 전화하기 때문에setSpeakers
모든 렌더에 재현될 것이다.#1을 고치면 스피커 구성요소가 같은 것을 받기 때문에 전혀 리렌더되지 않는다.
speaker
소품. 라는 사실.speaker.favorite
변화했다고 해서 재조명이 일어나지는 않는다.speaker
여전히 같은 대상이다.이 문제를 해결하려면 클릭 함수에 대한 사본을 반환하도록 하십시오.rec
와 함께favorite
기존 개체에서 전환하지 않고 플립:
import React, { useCallback, useState } from "react";
import Speaker from "./Speaker";
export default () => {
const speakersArray = [
{ name: "Crockford", id: 101, favorite: true },
{ name: "Gupta", id: 102, favorite: false },
{ name: "Ailes", id: 103, favorite: true },
];
const [speakers, setSpeakers] = useState(speakersArray);
const clickFunction = useCallback((speakerIdClicked) => {
var speakersArrayUpdated = speakers.map((rec) => {
if (rec.id === speakerIdClicked) {
return { ...rec, favorite: !rec.favorite }; // <= return a copy of rec
}
return rec;
});
setSpeakers(speakersArrayUpdated);
}, []); // <= remove speakers dependency
return (
<div>
{speakers.map((rec) => {
return (
<Speaker
speaker={rec}
key={rec.id}
clickFunction={clickFunction}
></Speaker>
);
})}
</div>
);
};
'Programing' 카테고리의 다른 글
생산 시 설계 양식 검증 문제 직면 (0) | 2022.03.27 |
---|---|
옵션 유형 힌트를 어떻게 사용해야 하는가? (0) | 2022.03.27 |
Python 3.x에서 목록을 반환하는 맵() 가져오기 (0) | 2022.03.27 |
Vue/Vuetify - 알 수 없는 사용자 지정 요소: - 구성 요소를 올바르게 등록하셨습니까? (0) | 2022.03.27 |
Vue.js. v-on:change를 사용하여 b-form-select의 선택된 항목을 얻는 방법에는 아무런 도움이 되지 않는가? (0) | 2022.03.27 |