Я использую перехватчики React и React memo, чтобы предотвратить повторный рендеринг моего функционального компонента, но не работает?

Я использую React.memo для управления повторным рендерингом, но мой компонент все равно повторно рендерится. мой код вроде этого:

в моем компоненте шаблона:

const Template = (props: Props) => {
  const { propsValue, data } = props
  const [value, setValue] = useState(propsValue)

  const handleChange = (value) => {
    setValue(value)
    props.onChange(value)
  }
  
  return (
    <div>
      {info.type === 'input' && <Input value={value} onChange={(event, val) => handleChange(val) onBlur={(event) => handleBlur()} />
      {info.type === 'image' && <Uploader multiple value={value} uploadUrl={data.uploadUrl} onChange={(val) => handleChange(val)} />
      {info.type === 'select' && <Select onChange={(val) => handleChange(val)} />
    </div>
  )
}

const areEqual = (prevProps, nextProps) => {
  if (JSON.stringify(prevProps) !== JSON.stringify(nextProps)) {
    return false
  }
  return true
}

export default React.memo(EditTemplate, areEqual)

в моем компоненте Uploader:

const Uploader = props => {
  const [value, setValue] = useState(props.value)
  let { uploadUrl, multiple } = props

  const handleChange = ({ file, fileList }) => {
    if (file.status === 'done') {
      setValue(fileList)
      props.onChange(fileList)
    } else {
      setValue(fileList)
    }
  }

  return (
     <div>
       <Upload fileList={value} multiple={multiple} action={uploadUrl} onChange={handleChange} />
     </div>
  )
}

const areEqual = (prevProps, nextProps) => {
  if (JSON.stringify(prevProps) !== JSON.stringify(nextProps)) {
    return false
  }
  return true
}

export default React.memo(Uploader, areEqual)

когда я изменяю значение в Select Component, areEqual кажется не работает, адрес всех изображений в Upload Component будет перезагружен. Зачем...?

спектакль такой:

Как я могу сделать?

3 ответа

Решение

Вы проходите onChange параметр к Uploader подобно onChange={(val) => handleChange(val)} так что это эффективно создает новую функцию для каждого рендера и, вероятно, React.memoдает ложные срабатывания из-за этого. Также вUploader у тебя есть props.onChange(fileList) а также fileList также может быть причиной, если каждый раз это другой экземпляр массива.

Помимо ответа @Ramesh Reddy, вы звонитеsetValue при выборе изменений тоже, это также может быть причиной, поскольку вы используете новое значение как опору для Uploader.

Если причина не в этом, вы можете добавить образец codeandbox с воспроизведением проблемы.

Повторный рендеринг может быть вызван изменением внутреннего состояния (setValue(value)). React.memo не предотвращает повторную визуализацию, вызванную изменением состояния.

React.memo проверяет только изменения свойств. Если ваш функциональный компонент, обернутый в React.memo, имеет в своей реализации хук useState или useContext, он все равно будет повторно отображаться при изменении состояния или контекста.

Документы

Большое спасибо всем ~ Я обнаружил, что тип моего значения в Uploader - это массив, поэтому при изменении Selectprops.onChange приведет к изменению значения, поэтому программа загрузки перезагрузится.

Я добавляю useEffect в компонент Uploader следующим образом: useEffect(() => { setValue(formatValue(props.value)) }, [JSON.stringify(props.value)]), и тогда изображения не будут перезагружаться...

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