【问题标题】:Can I call HOC directly from within JSX / TSX in React?我可以在 React 的 JSX / TSX 中直接调用 HOC 吗?
【发布时间】:2017-06-21 09:48:52
【问题描述】:

我在 TypeScript 中有一个 React HOC,但是当我从 TSX 组件 render 方法中调用它时,它似乎不起作用。这是一个例子:

export class HelloWorldComponent extends React.Component<{}, {}> {
    public render(): JSX.Element {
        return <div>Hello, world!</div>;
    }
}

export const withRedText = (Component) => {
    return class WithRedComponent extends React.Component<{}, {}> {
        public render(): JSX.Element {                
            return (
                <div style={{color: "red"}}>
                    <Component {...this.props} />
                </div>
            );
        }
    };
}; 

export const HelloWorldComponentWithRedText = withRedText(HelloWorldComponent);

我从这样的父 JSX 文件中调用它:

public render(): JSX.Element {
    return (
       <div>
           Test #1: <HelloWorldComponent/>
           Test #2: <HelloWorldComponentWithRedText />
           Test #3: { withRedText(<HelloWorldComponent />) }
       </div>
    )
}

第一个和第二个测试按预期工作——第二个测试中的文本是红色的。但是第三行什么也不渲染。我预计第二行和第三行是相同的。

当我使用调试器单步调试时,Test #2 的参数是 HelloWorldComponent 类型的组件,但 Test #3 看到的是 Component = Object {$$typeof: Symbol(react.element), ...}。

有没有办法在 JSX/TSX 文件中使用 { withRedText(&lt;HelloWorldComponent /&gt;) } 之类的语法动态包装组件?

(TypeScript 2.1.4 和 React 15.4.0)

Here it is on CodePen

【问题讨论】:

标签: javascript reactjs typescript jsx tsx


【解决方案1】:

我认为您不能直接/隐式地从 JSX 调用 HOC。考虑 JSX 的实现以及 HOC 的工作方式,我认为这对性能没有好处:每次组件重新渲染时,它都会再次调用 HOC 函数,重新创建包装的组件类,然后调用它。

不过,您通常可以通过创建一个将另一个组件作为参数的组件来获得类似的效果:

const WithRedText = ({component: Component, children, ...props}) => (
    <div style={{color: "red"}}>
      <Component {...props}>{children}</Component>
    </div>
);

(我将 component 传递为小写,因为这似乎是 props 的约定,但在 WithRedText 中,我将其大写,因为这是 JSX 识别自定义组件而不是 HTML 标记的方式。)

然后,使用它:

ReactDOM.render(
    <div className="container">
        <WithRedText component={HelloWorldComponent} />
    </div>,
);

见http://codepen.io/joshkel/pen/MJGLOQ。

【讨论】:

  • 好的,有道理,谢谢。我最终想知道是否可以动态堆叠它们,例如{withFeatureOne(withFeatureTwo(&lt;HelloWorldComponent /&gt;))} 但也许这只能静态工作。
  • 在考虑了您的回答后,我意识到我问错了问题。我不能像我想的那样调用 HOC,但我仍然可以使用 React.CreateComponent() 获得不错的语法。我可以使用像 export const createComponent = (component, ...args) =&gt; React.createElement(component, args); 这样的辅助函数来清理它,然后像这样从 JSX 调用它:{createComponent(withRedText(HelloWorldComponent))。我可以尽可能多地链接它们,而且语法并不难看。
【解决方案2】:

这是因为在测试#3 中你传递了一个实例:&lt;HelloWorldComponent /&gt;,而不是类型/类HelloWorldComponent。 JSX 被转译成大量的对象实例化样板文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2018-01-07
    • 2017-11-03
    • 1970-01-01
    • 2017-05-06
    • 2022-01-01
    • 1970-01-01
    相关资源
    最近更新 更多