Реагировать на компонент более высокого порядка. Предупреждение. Невозможно обновить компонент внутри тела функции другого компонента. - PullRequest
0 голосов
/ 22 апреля 2020

Я сделал довольно простой компонент высшего порядка, который извлекает данные из конечной точки API и отображает счетчик загрузки, сообщение об ошибке при сбое или компонент при успехе.

Компонент работает нормально , но я получаю следующее сообщение об ошибке:

Warning: Cannot update a component from inside the function body of a different component. in Unknown (at ApiData.tsx:34) <- эта строка: <code>ok: value => <WrappedComponent data={value} />

Читая похожие посты, я понимаю, что React может быть немного переусердствовал при отображении этого сообщение. Я использую полностью неизменный магазин Redux и не использую неработающие компоненты. Я боюсь, что из-за того, что я получаю это предупреждение, если я попытаюсь расширить этот компонент позже (скажем, с помощью автоматического обновления API время от времени), обновления не будут запускаться должным образом. Кроме того, это предупреждающее сообщение - мы должны обратить внимание;)

Ниже приведен код HO C

import React, { ComponentType } from 'react'
import { IResult } from 'typescript-monads'
import { useDispatch } from '../../store'
import { PayloadActionCreator } from 'typesafe-actions'
import { Preloader, PreloaderSize } from 'react-materialize'
import styles from './ApiData.module.scss'

interface ApiProps<TKey, TData> {
  key: TKey
  data?: IResult<TData, Error> | "loading"
  get: { request: PayloadActionCreator<string, TKey> }
  loaderSize?: PreloaderSize | "inline"
}

export interface DataProps<TData> {
  data: TData
}

export default <TKey, TData>({ key, data, get, loaderSize }: ApiProps<TKey, TData>) =>
  (WrappedComponent: ComponentType<DataProps<TData>>) => {
    const dispatch = useDispatch()
    if (!data) {
      dispatch(get.request(key))
      return <span>&nbsp;</span>
    } else if (data === "loading") {
      if (!loaderSize || loaderSize === "inline") {
        return <span><Preloader className={styles.preloader} /></span>
      } else {
        return <Preloader size={loaderSize} />
      }
    } else {
      return data.match({
        fail: error => <span>An error occurred: {error.message}</span>,
        ok: value => <WrappedComponent data={value} />
      })
    }
  }

Вот пример того, как он используется:

const somePart = ApiData<SomeObjectKey, SomeObject>({...})
...
return <div>{somePart(SomeComponent)}</div>

Может кто-нибудь подсказать, почему возникает это предупреждение, и как его убрать / устранить? Спасибо.

РЕДАКТИРОВАТЬ: Было предложено, что data.match может быть проблемой - я тоже попробовал следующее, и это все еще ошибки:

if (data.isFail()) {
  return <span>An error occurred: {data.unwrapFail()}</span>
} else {
  return <WrappedComponent data={data.unwrap()} />
}

1 Ответ

0 голосов
/ 22 апреля 2020

Я заметил, что ваши параметры могли быть в неправильном порядке. Обычно для HO C вы хотите сначала взять обернутый компонент и вернуть функцию, которая принимает реквизиты и возвращает JSX, включающий обернутый компонент некоторым образом.

// next two lines have been swapped
export default (WrappedComponent: ComponentType<DataProps<TData>>) => { 
  return ({ key, data, get, loaderSize }: ApiProps<TKey, TData>) => {
    const dispatch = useDispatch()
    if (!data) {
      dispatch(get.request(key))
      return <span>&nbsp;</span>
    } else if (data === "loading") {
      if (!loaderSize || loaderSize === "inline") {
        return <span><Preloader className={styles.preloader} /></span>
      } else {
        return <Preloader size={loaderSize} />
      }
    } else {
      if (data.isFail()) {
        return <span>An error occurred: {data.unwrapFail()}</span>
      } else {
        return <WrappedComponent data={data.unwrap()} />
      }
    }
  }
}

Теперь вы можете использовать свой HO C следующим образом:

import HOC from "./hoc-file"

function OriginalComponent(/* ... */) { /* ... */ }

const WrappedComponent = HOC(OriginalComponent);

ReactDOM.render(<WrappedComponent {...props} />, rootDomElement);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...