React Memo обновляет состояние родительского компонента

У меня есть такие компоненты, как показано ниже

QuestionAnsPage.component(родительский)

export interface FieldsDatatype {
  id: string | number;
  attributeId: string | number,
  mainQuestionFlg?: boolean;
  mainQuestionId: number | string,
  question: string;
  **values: Array<number | string>;**
  fieldType: number;
  mandatory: boolean;
  isNumber: boolean;
  pattern?: string;
  max?: string | number;
  min?: string | number;
  displayInline?: boolean;
  error?: boolean;
  message?: string;
  options: OptionsType[] | undefined | null;
  storedColumn?: string;
  storedJson?: string;
}

type Props = {
  data?: FieldsDatatype[];
  country: string;
  handleOnConfirmClick: (data: FieldsDatatype[]) => void;
  handleOnCancelClick: () => void;
  isLoading?: boolean;
  errorMessage?: Error;
  id: string | number;
}
const QuestionAnsPageComponent = (props: Props): JSX.Element => {
    const [data, setData] = useState([]);
    
    useEffect(() => {
        if (props.data) {
          setData(props.data);
        }
      }, [props.data]);
.
.
..
}

QuestionAnswer.componet(ребенок)

type Props = {
  data: FieldsDatatype;
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
  onChangeSelect?: (id: string | number, value: string | number) => void;
  onDateChange?: (fieldName: string | number, value: string) => void;
  onBlur?: (event: React.FocusEvent<HTMLInputElement | HTMLButtonElement | HTMLTextAreaElement>) => void;
  country: string;
}

   const QuestionAnswerComponent = (props: Props): JSX.Element => {
    function comparisonForRerender(prevProps: Props, nextProps: Props): boolean {
         console.log('nextProps:', nextProps.data.values, nextProps.data.id);
         console.log('prevProps:', prevProps.data.values, prevProps.data.id);
      const nextValArr = [...nextProps.data.values];
      const prevValArr = prevProps.data ? [...prevProps.data.values] : [];
      const nextValuesLen = nextValArr.length;
      const prevValuesLen = prevValArr.length;
      if (nextValArr
        && prevValArr
        && nextValuesLen > 1
        && nextProps.data.fieldType === FIELDS_TYPE.CHECKBOX) {
        return (nextValuesLen === prevValuesLen
              && JSON.stringify(prevValArr) === JSON.stringify(prevValArr));
      } else if (nextValArr
        && prevValArr
        && nextValuesLen > 0
        && prevValuesLen > 0
        && nextProps.data.id === prevProps.data.id) {
        **return (prevValArr.includes(nextValArr[0]));**
      }
      return false;
    }
    }

    export default React.memo(QuestionAnswerComponent, comparisonForRerender);

Я использую React.memo для повышения производительности. Я хочу отображать мой дочерний компонент при изменении "props.data.values"(тип этого поля - Array). для этого я создал функцию compareForRerender.

Я пытаюсь сравнить props.data.value в функции, например:(prevValArr.includes(nextValArr[0]))

Но эта функция вызывает какое-то странное поведение, состояние моего родительского компонента каким-то образом сбрасывается до старого значения (в данном случае данные).

Я не уверен, но эта функция сравнения каким-то образом меняет состояние моего родительского компонента. Если я удалю эту функцию, она будет работать нормально.

1 ответ

Ваш родительский компонент обновляется, потому что props.dataэто массив. В массиве зависимостей проверяется только указатель на массив. useEffect функции, вам нужно будет сравнить значение каждого элемента в массиве или выбрать другую переменную зависимости, возможно, что-то вроде длины массива.

Другие вопросы по тегам