链接高阶组件时出现问题 <Functions are not valid as a React child.>

Problem chaining Higher Order Components <Functions are not valid as a React child.>

我创建了一个示例项目来演示我在尝试同时使用两个高阶组件 (hoc) 时遇到的问题。

首次隔离(无错误)

==================================

第一个 hoc withStuff 接受一个注入的参数和一个 prop 并将 sum 传递给包装的组件。

// withStuff.js
const withStuff = ({argNumber}) => (BaseComponent) => ({propNumber, ...passThroughProps}) => {
  const sum = argNumber+propNumber
  return <BaseComponent sum={sum} {...passThroughProps} />
}

export default withStuff

第二个 hoc withExtra 采用注入函数并将结果加倍,将 double 传递给包装组件。

// withExtra.js
const withExtra = (extraFunction) => (BaseComponent) => ({...passThroughProps}) => {
  const double = 2*extraFunction()
  return <BaseComponent double={double} {...passThroughProps} />
}

export default withExtra

这就是 Base 组件的用法,例如 withStuff(到目前为止一切正常)。

// Base.js
import withStuff from './withStuff'

const Base = ({content, sum}) => <div>{content} -sum:{sum}</div>

export default withStuff({argNumber:2})(Base)

=================================

现在问题来了:试图在 withStuff:

中使用 withExtra
import withExtra from './withExtra'

const withStuff = ({argNumber}) => (BaseComponent) => ({propNumber, ...passThroughProps}) => {
  const sum = argNumber+propNumber
  // this does not work
  return withExtra(()=>sum)(<BaseComponent sum={sum} {...passThroughProps}/>)
}

export default withStuff

这returns一个错误:

Warning: Functions are not valid as a React child.

是因为现在 withStuff 返回的是一个临时函数而不是一个组件吗?该函数 returns 本身就是一个组件,所以我看不出问题所在。如何解决?

在此处注意代码和框:https://codesandbox.io/s/github/snirp/hoc-test

withExtra应该是得到一个组件,所以我认为这一行

return withExtra(()=>sum)(<BaseComponent sum={sum} {...passThroughProps}/>)

应该是:

return withExtra(()=>sum)(BaseComponent)

return withExtra(()=>sum)(() => <BaseComponent sum={sum} {...passThroughProps}/>)

问题是您传递的是 ReactElement 而不是组件。

参考what is JSX幕后。

请注意,如果您想向给定的 ReactElement 添加其他属性,您可以 use cloneElement.

const withStuff = ({ argNumber }) => BaseComponent => ({
  propNumber,
  ...passThroughProps
}) => {
  const sum = argNumber + propNumber;

  const callback = () => sum;

  // Like so you passing the node which leads to error
  // return withExtra(callback)(<BaseComponent sum={sum} {...passThroughProps}

  // Passing the reference
  return withExtra(callback)(BaseComponent);

  // Passing with additional props
  // return withExtra(callback)(React.cloneElement(BaseComponent, ...));

  // Equivalent
  // const WithExtraProps = withExtra(() => sum)(BaseComponent);
  // return <WithExtraProps sum={sum} {...passThroughProps} />;
};

您将 JSX 传递给 withExtra 而不是组件,请像这样更改 withStuff

const withStuff = ({argNumber}) => (BaseComponent) => ({propNumber, ...passThroughProps}) => {
  const sum = argNumber+propNumber

  // this works
  // return <BaseComponent sum={sum} {...passThroughProps} />

  const WithExtraComponent = withExtra(()=>sum)(BaseComponent);
  return <WithExtraComponent sum={sum} {...passThroughProps}/>


}

https://codesandbox.io/s/hoc-test-pm02u

这应该可以解决:

return withExtra(() => sum)(BaseComponent)();

https://codesandbox.io/s/hoc-test-thxh0