简体   繁体   English

我可以在 React 的 JSX / TSX 中直接调用 HOC 吗?

[英]Can I call HOC directly from within JSX / TSX in React?

I have a React HOC in TypeScript, but it doesn't seem to work when I call it from within a TSX Component render method.我在 TypeScript 中有一个 React HOC,但是当我从 TSX 组件render方法中调用它时它似乎不起作用。 Here's an example:下面是一个例子:

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);

I'm calling this from a parent JSX file like this:我从这样的父 JSX 文件中调用它:

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

The first and second tests work as expected---the text is red in the second one.第一个和第二个测试按预期工作——第二个中的文本是红色的。 But the third line renders nothing.但第三行什么都不渲染。 I expected the second and third lines to be the same.我预计第二行和第三行是相同的。

When I step through it with the debugger, the argument to Test #2 is a Component of type HelloWorldComponent , but Test #3 is seeing a Component = Object {$$typeof: Symbol(react.element), ...} .当我使用调试器逐步完成它时,测试 #2 的参数是HelloWorldComponent类型的 Component ,但测试 #3 看到的是Component = Object {$$typeof: Symbol(react.element), ...}

Is there a way to dynamically wrap a Component with syntax like { withRedText(<HelloWorldComponent />) } from within the JSX/TSX file?有没有办法在 JSX/TSX 文件中使用{ withRedText(<HelloWorldComponent />) }之类的语法动态包装组件?

(TypeScript 2.1.4 & React 15.4.0) (TypeScript 2.1.4 & React 15.4.0)

Here it is on CodePen这是在 CodePen 上

That is because in test #3 you pass it an instance: <HelloWorldComponent /> , instead of the type/class HelloWorldComponent .那是因为在测试 #3 中,您向它传递了一个实例: <HelloWorldComponent /> ,而不是类型/类HelloWorldComponent The JSX gets transpiled to what amounts to a lot of object instantiation boilerplate. JSX 被转译为大量对象实例化样板。

I don't think that you can invoke a HOC directly / implicitly from JSX.我不认为您可以从 JSX 直接/隐式调用 HOC。 Thinking about the implementation of JSX and how HOCs work, I don't think it would be good for performance: every time the component re-renders, it calls the HOC function again, re-creates the wrapped component class, then invokes it.考虑 JSX 的实现以及 HOC 的工作方式,我认为这对性能没有好处:每次组件重新渲染时,它都会再次调用 HOC 函数,重新创建包装的组件类,然后调用它。

You can often get a similar effect, though, by creating a component that takes another component as a parameter:但是,您通常可以通过创建一个将另一个组件作为参数的组件来获得类似的效果:

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

(I'm passing component as lowercase, because that seems to be the convention for props, but within WithRedText , I uppercase it, because that's how JSX identifies custom components as opposed to HTML tags.) (我以小写形式传递component ,因为这似乎是 props 的约定,但在WithRedText ,我将其大写,因为这是 JSX 识别自定义组件而不是 HTML 标签的方式。)

Then, to use it:然后,使用它:

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

See http://codepen.io/joshkel/pen/MJGLOQ .请参阅http://codepen.io/joshkel/pen/MJGLOQ

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM