React에서는 일치하지 않는 참조 식별자로 인해 단일 요소가 변경되는 경우 모든 구성 요소를 다시 렌더링하지 않기 위해 항목 목록(루프를 통해 생성됨)의 함수를 기억하기 위해 useCallback
와 같은 것을 자주 사용해야 합니다... 불행하게도, 이는 만료되기가 놀랍게도 어렵습니다. 예를 들어 다음 코드를 고려해 보세요.
개미 디자인 등에서 제공하는 외부 구성 요소는 어디에 Button
있습니까? 이 함수 참조는 인라인이므로 렌더링할 때마다 달라지므로 강제로 다시 렌더링됩니다.
이 문제를 방지하기 위해 다른 해결책을 생각해 볼 수 있습니다. 즉, 새 구성 요소를 만드는 것입니다. MyButton
,它接受两个属性 index={i}
和 onClick
而不是单个 onClick
,并将参数 index
附加到任何调用onClick
:
이 방법은 작동하지만 여러 가지 이유로 매우 비실용적입니다.
Button
와 같은 외부 라이브러리의 모든 요소를 <MyButton index1={index1} index2={index2} index3={index3 onClick={myFunction}>
,这意味着我需要完全通用地创建一个更复杂的版本 MyButton
来检查嵌套级别的数量。我无法使用 index={[index1,index2,index3]}
이 조합은 좋지 않습니다. 요소를 여러 목록에 중첩하려면 목록의 각 수준에 새 색인을 추가해야 하기 때문에 더 지저분해질 것입니다. 예를 들어 index
내가 아는 한 더 나은 솔루션이 없나요? 목록이 어디에나 있다는 점을 고려하면 이에 대한 적절한 해결책이 없다는 것을 믿을 수 없으며 이에 대한 문서가 얼마나 적은지 보고 놀랐습니다.
편집
나는 이것을 시도한다:으아악
다음과 같이 사용하세요:onClick
,onChange
,...),如果我有它就无法直接工作多个属性(例如 onClick
和 onChange
으아악
하지만 여전히 완벽하지는 않습니다. 특히 다양한 중첩 수준에 대한 래퍼가 필요하고 새 속성을 대상으로 할 때마다 새 버전을 만들어야 합니다(). 이전에 본 적이 없으므로 더 나은 솔루션을 원합니다. . 편집
fast-memoize를 포함하여 다양한 아이디어를 시도했지만 여전히 모든 결과를 이해하지 못합니다. 때로는 fast-memoize가 작동하고 때로는 실패합니다... fast-memoize가 권장되는 솔루션인지는 모르겠습니다. 이러한 일반적인 사용 사례에 타사 도구를 사용하는 것은 이상해 보입니다. 여기에서 내 테스트를 확인하세요 https://codesandbox.io/embed/magical-dawn-67mgxp?fontsize=14&hidenavigation=1&theme=dark🎜
여기에서 테스트하세요 https://codesandbox.io /s/sharp-wind-rd48q4?file=/src/App.js
경고: 저는 React 전문가가 아니므로(따라서 제 질문입니다!) 아래에 댓글을 달거나 이 솔루션이 React에서 표준적인 방법이라고 생각한다면 +1을 추가하세요. 그렇지 않으면 -1을 추가하세요. ^^). 또한 다른 솔루션이 실패하는 이유가 궁금합니다(예: Proxy-memoize(실제로 캐싱이 없는 것보다 10배 더 오래 걸리고 전혀 캐시하지 않음) 또는 fast-memoize(방법에 따라 항상 캐시하지 않음)를 기반으로 함 저는 그것을 사용합니다 )), 알고 계신다면 저도 알고 싶습니다)
저는 이 문제에 거의 관심이 없기 때문에 다양한 옵션(메모리 없음, 외부 라이브러리 사용(빠른 메모리 대 프록시 메모리), 래퍼 사용), 외부 구성 요소 사용 등에 대해 여러 가지 솔루션(14개!)을 벤치마킹해 보았습니다. .
가장 좋은 방법은 마지막 버튼뿐만 아니라 목록의 전체 요소를 포함하는 새 구성 요소를 만드는 것 같습니다. 이를 통해 매우 깔끔한 코드가 가능하고(목록과 항목에 대해 두 개의 구성 요소를 생성해야 하는 경우에도 적어도 의미상으로는 의미가 있음) 외부 라이브러리를 피하고 내가 시도한 다른 모든 것보다 더 효율적인 것 같습니다(적어도 제 생각에는 (예를 들어):
으아악부모 구성 요소에서 자식 구성 요소로 많은 콘텐츠를 전달해야 하기 때문에 여전히 이 솔루션이 마음에 들지 않지만 이것이 제가 얻을 수 있는 최고의 솔루션인 것 같습니다...
내 시도 목록을 여기에서 볼 수 있습니다. 저는 아래 코드를 사용했습니다. 다음은 프로파일러의 보기입니다(기술적으로 모든 버전 간의 시간 차이는 그다지 크지 않습니다(프록시 메모화를 사용하는 버전 7을 제외하고, 버전이 10배 정도 더 길었고 차트를 읽기 더 어렵게 만들고 있었기 때문에 제거했습니다).) , 그러나 항목을 그리기가 더 복잡한 긴 목록에서는 이 차이가 더 커질 것으로 예상됩니다(여기에는 텍스트와 버튼이 하나만 있습니다). 모든 버전이 정확히 동일하지는 않습니다(일부는
,一些
, 일부 일반 목록, 일부 Ant 설계 목록...). 따라서 시간 비교는 동일한 작업을 수행하는 버전 간에만 의미가 있습니다. 어쨌든, 내 주요 관심사는 캐시된 것과 캐시되지 않은 것을 확인하는 것입니다. 이는 프로파일러에서 명확하게 표시됩니다(연한 회색 블록이 캐시됨).
또 다른 흥미로운 사실은 적어도 간단한 구성 요소(여기서는 크기 5, 텍스트 하나와 버튼 하나)에 대해서는 개선이 크지 않을 수 있으므로 기억하기 전에 벤치마킹하고 싶을 수도 있다는 것입니다.
으아악