我创建了一个示例项目来演示尝试同时使用两个高阶组件 (hoc( 时遇到的问题。
隔离第一(无错误(
====
==================================第一个 hocwithStuff
接受注入的参数和 prop,并将sum
传递给包装的组件。
// withStuff.js
const withStuff = ({argNumber}) => (BaseComponent) => ({propNumber, ...passThroughProps}) => {
const sum = argNumber+propNumber
return <BaseComponent sum={sum} {...passThroughProps} />
}
export default withStuff
第二个 hocwithExtra
采用注入的函数并将结果加倍,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
这将返回一个错误:
Warning: Functions are not valid as a React child.
是因为现在withStuff
返回的是 hoc 函数而不是组件吗?该函数返回一个组件本身,所以我看不到问题。如何解决这个问题?
注意此处的代码沙盒:
https://codesandbox.io/s/github/snirp/hoc-testwithExtra
应该得到一个组件,所以我认为这一行
return withExtra(()=>sum)(<BaseComponent sum={sum} {...passThroughProps}/>)
应该是:
return withExtra(()=>sum)(BaseComponent)
或
return withExtra(()=>sum)(() => <BaseComponent sum={sum} {...passThroughProps}/>)
问题是你传递的是ReactElement
而不是组件。
参考幕后what is JSX
。
请注意,如果要向给定ReactElement
添加其他属性,可以使用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