反应高阶组件 - 警告:无法从不同组件的函数体内部更新组件
React higher-order component - Warning: Cannot update a component from inside the function body of a different component
我制作了一个非常简单的高阶组件,它从 API 端点获取数据,并显示加载微调器、失败时的错误消息或成功时的组件。
该组件工作正常,但我收到以下错误消息:
Warning: Cannot update a component from inside the function body of a different component.
in Unknown (at ApiData.tsx:34)
<-- 这一行:ok: value => <WrappedComponent data={value} />
通过阅读类似的帖子,我了解到 React 在显示此消息时可能有点过分热心。我正在使用完全不可变的 Redux 存储,并且不使用任何非功能性组件。恐怕因为我收到此警告,如果我稍后尝试扩展此组件(例如,通过每隔一段时间自动刷新 API )更新将无法正确触发。另外,这是一条警告信息 - 我们应该注意 ;)
下面是 HOC 的代码
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> </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>
任何人都可以建议为什么会发出此警告,以及如何 remove/resolve?谢谢。
编辑:有人建议 data.match
可能是个问题 - 我也尝试了以下方法,但仍然出错:
if (data.isFail()) {
return <span>An error occurred: {data.unwrapFail()}</span>
} else {
return <WrappedComponent data={data.unwrap()} />
}
我注意到您的参数顺序可能有误。通常对于 HOC,您希望首先采用包装组件,然后 return 一个采用 props 的函数和 returns 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> </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()} />
}
}
}
}
现在您可以像这样使用您的 HOC:
import HOC from "./hoc-file"
function OriginalComponent(/* ... */) { /* ... */ }
const WrappedComponent = HOC(OriginalComponent);
ReactDOM.render(<WrappedComponent {...props} />, rootDomElement);
我制作了一个非常简单的高阶组件,它从 API 端点获取数据,并显示加载微调器、失败时的错误消息或成功时的组件。
该组件工作正常,但我收到以下错误消息:
Warning: Cannot update a component from inside the function body of a different component.
in Unknown (at ApiData.tsx:34)
<-- 这一行:ok: value => <WrappedComponent data={value} />
通过阅读类似的帖子,我了解到 React 在显示此消息时可能有点过分热心。我正在使用完全不可变的 Redux 存储,并且不使用任何非功能性组件。恐怕因为我收到此警告,如果我稍后尝试扩展此组件(例如,通过每隔一段时间自动刷新 API )更新将无法正确触发。另外,这是一条警告信息 - 我们应该注意 ;)
下面是 HOC 的代码
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> </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>
任何人都可以建议为什么会发出此警告,以及如何 remove/resolve?谢谢。
编辑:有人建议 data.match
可能是个问题 - 我也尝试了以下方法,但仍然出错:
if (data.isFail()) {
return <span>An error occurred: {data.unwrapFail()}</span>
} else {
return <WrappedComponent data={data.unwrap()} />
}
我注意到您的参数顺序可能有误。通常对于 HOC,您希望首先采用包装组件,然后 return 一个采用 props 的函数和 returns 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> </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()} />
}
}
}
}
现在您可以像这样使用您的 HOC:
import HOC from "./hoc-file"
function OriginalComponent(/* ... */) { /* ... */ }
const WrappedComponent = HOC(OriginalComponent);
ReactDOM.render(<WrappedComponent {...props} />, rootDomElement);