簡體   English   中英

功能子組件不會在道具更改時重新渲染

[英]A functional subcomponent doesn't rerender on props change

我有一個非常重的(計算上的)功能組件(父),它沒有狀態,並且具有本地狀態的子組件很少。 孩子只依賴於從父母發送的道具。

我將一個函數傳遞給其中一個孩子 (ChildA) 以更改 Parent 上變量的值。

此變量是不同子組件 (ChildB) 的道具之一,它具有基於該道具的狀態並在 useEffect 鈎子中更新它。

當作為 prop 傳遞的值在 Parent 組件上發生更改時,ChildB 組件不會重新渲染。

當然,在 Parent 上引入狀態(useState 鈎子)修復了這個問題,但會一遍又一遍地重新渲染父級並殺死性能,因為 Parent 有 500 多個嵌套組件,這些組件都被重新渲染。

引入某種類型的 Store(Redux、MobX)可能會解決這個問題,但這將是一種矯枉過正。

一個簡化的例子:

import React, { useEffect, useState } from "react";

export default function App() {
  return <Parent />    
}

const ChildA = ({ onAction }) => {
  return <button onClick={onAction}>CLICK</button>;
};

const ChildB = ({ coreValue }) => {
  const [value, setValue] = useState(0);

  useEffect(() => {
    setValue(coreValue);
  }, [coreValue]);

  return <div>My value: {value}</div>;
};

const Parent = () => {
  let calculatedValue = 0;

  const changeValue = () => {
    calculatedValue += Math.random();
  };

  return (
    <div>
      <ChildA onAction={changeValue} />
      <ChildB coreValue={calculatedValue} />
    </div>
  );
};

你可以在這里測試代碼: https : //codesandbox.io/s/vigilant-wave-r27rg

如何在道具更改時僅重新渲染 ChildB?

您必須將值存儲在父組件狀態中,並將父組件狀態值發送到 ChildB,在那里您不需要維護狀態和 useEffect 鈎子來捕獲更改。 請參閱此處的代碼: https : //codesandbox.io/s/adoring-chatelet-sjjfs

import React, { useState } from "react";
export default function App() {
  return <Parent />;
}
const ChildA = ({ onAction }) => {
  return <button onClick={onAction}>CLICK</button>;
};
const ChildB = ({ coreValue }) => {
  return <div>My value: {coreValue}</div>;
};
const Parent = () => {
  const [value, setValue] = useState(0);
  const changeValue = () => {
    setValue(value + Math.random());
  };
  return (
    <div>
       <ChildA onAction={changeValue} />
       <ChildB coreValue={value} />
    </div>
  );
};

React 的useCallbackmemo防止了不必要的重新渲染。 請注意,無論ParentChildB狀態更改的次數如何,ChildA 都不會重新呈現。 此外,當前的例子並不需要useState / useEffectChildB

https://codesandbox.io/s/usecallback-and-memo-ptkuj

import React, { useEffect, useState, memo, useCallback } from "react";

export default function App() {
  return <Parent />;
}

const ChildA = memo(({ onAction }) => {
  console.log("ChildA rendering");
  return <button onClick={onAction}>CLICK</button>;
});

const ChildB = memo(({ coreValue }) => {
  const [value, setValue] = useState(0);

  useEffect(() => {
    setValue(coreValue);
  }, [coreValue]);

  return <div>My value: {value}</div>;
});

const Parent = () => {
  const [calculatedValue, setCalculatedValue] = useState(0);

  const changeValue = useCallback(() => {
    setCalculatedValue(c => (c += Math.random()));
  }, []);

  return (
    <div>
      <ChildA onAction={changeValue} />
      <ChildB coreValue={calculatedValue} />
    </div>
  );
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM