루프 기반 매개변수를 사용하여 React에서 useCallback 함수를 효율적으로 정의합니다.
P粉550823577
P粉550823577 2024-01-16 14:06:30
0
2
450

질문

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내가 아는 한
  • es에는 명명 규칙이 없습니다. 즉, 프로젝트 간에 코드를 공유하거나 라이브러리를 개발하기가 더 어렵습니다

더 나은 솔루션이 없나요? 목록이 어디에나 있다는 점을 고려하면 이에 대한 적절한 해결책이 없다는 것을 믿을 수 없으며 이에 대한 문서가 얼마나 적은지 보고 놀랐습니다.

편집

나는 이것을 시도한다:

으아악

다음과 같이 사용하세요: onClickonChange,...),如果我有它就无法直接工作多个属性(例如 onClickonChange 으아악 하지만 여전히 완벽하지는 않습니다. 특히 다양한 중첩 수준에 대한 래퍼가 필요하고 새 속성을 대상으로 할 때마다 새 버전을 만들어야 합니다(

). 이전에 본 적이 없으므로 더 나은 솔루션을 원합니다. .

편집

fast-memoize를 포함하여 다양한 아이디어를 시도했지만 여전히 모든 결과를 이해하지 못합니다. 때로는 fast-memoize가 작동하고 때로는 실패합니다... fast-memoize가 권장되는 솔루션인지는 모르겠습니다. 이러한 일반적인 사용 사례에 타사 도구를 사용하는 것은 이상해 보입니다. 여기에서 내 테스트를 확인하세요 https://codesandbox.io/embed/magical-dawn-67mgxp?fontsize=14&hidenavigation=1&theme=dark🎜
P粉550823577
P粉550823577

모든 응답(2)
P粉001206492
  1. 우선, 인덱스를 매개변수, 소품 또는 키로 사용하는 것은 권장하지 않습니다. 첫 번째 인덱스를 삭제하면 모든 하위 구성 요소가 다시 렌더링되기 때문입니다.
  2. 그리고 장면에 따라 다시 렌더링하지 않으려는 경우 다음과 같이 참조할 수 있는 몇 가지 아이디어가 있습니다.
으아악 으아악

여기에서 테스트하세요 https://codesandbox.io /s/sharp-wind-rd48q4?file=/src/App.js

P粉916760429

경고: 저는 React 전문가가 아니므로(따라서 제 질문입니다!) 아래에 댓글을 달거나 이 솔루션이 React에서 표준적인 방법이라고 생각한다면 +1을 추가하세요. 그렇지 않으면 -1을 추가하세요. ^^). 또한 다른 솔루션이 실패하는 이유가 궁금합니다(예: Proxy-memoize(실제로 캐싱이 없는 것보다 10배 더 오래 걸리고 전혀 캐시하지 않음) 또는 fast-memoize(방법에 따라 항상 캐시하지 않음)를 기반으로 함 저는 그것을 사용합니다 )), 알고 계신다면 저도 알고 싶습니다)

저는 이 문제에 거의 관심이 없기 때문에 다양한 옵션(메모리 없음, 외부 라이브러리 사용(빠른 메모리 대 프록시 메모리), 래퍼 사용), 외부 구성 요소 사용 등에 대해 여러 가지 솔루션(14개!)을 벤치마킹해 보았습니다. .

가장 좋은 방법은 마지막 버튼뿐만 아니라 목록의 전체 요소를 포함하는 새 구성 요소를 만드는 것 같습니다. 이를 통해 매우 깔끔한 코드가 가능하고(목록과 항목에 대해 두 개의 구성 요소를 생성해야 하는 경우에도 적어도 의미상으로는 의미가 있음) 외부 라이브러리를 피하고 내가 시도한 다른 모든 것보다 더 효율적인 것 같습니다(적어도 제 생각에는 (예를 들어):

으아악

부모 구성 요소에서 자식 구성 요소로 많은 콘텐츠를 전달해야 하기 때문에 여전히 이 솔루션이 마음에 들지 않지만 이것이 제가 얻을 수 있는 최고의 솔루션인 것 같습니다...

내 시도 목록을 여기에서 볼 수 있습니다. 저는 아래 코드를 사용했습니다. 다음은 프로파일러의 보기입니다(기술적으로 모든 버전 간의 시간 차이는 그다지 크지 않습니다(프록시 메모화를 사용하는 버전 7을 제외하고, 버전이 10배 정도 더 길었고 차트를 읽기 더 어렵게 만들고 있었기 때문에 제거했습니다).) , 그러나 항목을 그리기가 더 복잡한 긴 목록에서는 이 차이가 더 커질 것으로 예상됩니다(여기에는 텍스트와 버튼이 하나만 있습니다). 모든 버전이 정확히 동일하지는 않습니다(일부는 ,一些 , 일부 일반 목록, 일부 Ant 설계 목록...). 따라서 시간 비교는 동일한 작업을 수행하는 버전 간에만 의미가 있습니다. 어쨌든, 내 주요 관심사는 캐시된 것과 캐시되지 않은 것을 확인하는 것입니다. 이는 프로파일러에서 명확하게 표시됩니다(연한 회색 블록이 캐시됨).

또 다른 흥미로운 사실은 적어도 간단한 구성 요소(여기서는 크기 5, 텍스트 하나와 버튼 하나)에 대해서는 개선이 크지 않을 수 있으므로 기억하기 전에 벤치마킹하고 싶을 수도 있다는 것입니다.

으아악
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿