2017-02-03 9 views
2

У меня есть React HOC в TypeScript, но он не работает, когда я вызываю его из метода TSX render. Вот пример:Можно ли вызвать HOC непосредственно из JSX/TSX в React?

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), ...}.

Есть ли способ динамически обернуть компонент с синтаксисом, например { withRedText(<HelloWorldComponent />) }, из файла JSX/TSX?

(машинопись 2.1.4 & Реагировать 15.4.0)

Here it is on CodePen

+0

Вот версия JavaScript: http://codepen.io/mikebridge/pen/mRLvRd – mikebridge

ответ

1

Я не думаю, что вы можете напрямую или косвенно ссылаться на HOC из JSX. Размышляя о внедрении JSX и о том, как работают HOC, я не думаю, что это было бы хорошо для производительности: каждый раз, когда компонент повторно отображается, он снова вызывает функцию HOC, повторно создает класс завершенных компонентов, а затем вызывает его.

Вы часто можете получить подобный эффект, хотя, создавая компонент, который принимает другой компонент в качестве параметра:

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

(я передаю component в нижнем регистре, потому что, как представляется, Конвенция . реквизита, но в WithRedText, я прописной, потому что это как JSX определяет пользовательские компоненты, в отличие от HTML-тегов)

Затем, чтобы использовать его:

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

См. http://codepen.io/joshkel/pen/MJGLOQ.

+0

Хорошо, это имеет смысл, спасибо. Мне было интересно узнать, могу ли я складывать их динамически, например. '{withFeatureOne (withFeatureTwo ())}, но, возможно, это будет работать только статически. – mikebridge

+0

Подумав о вашем ответе, я понял, что задал неправильный вопрос. Я не могу назвать HOC, как я думал, но я все еще могу получить приличный синтаксис, используя 'React.CreateComponent()'. Я мог бы очистить его с помощью вспомогательной функции, такой как 'export const createComponent = (component, ... args) => React.createElement (component, args);' затем вызывать это из JSX следующим образом: '{createComponent (withRedText (HelloWorldComponent)) '. Я могу связать их столько, сколько захочу, и синтаксис не слишком сложный для глаз. – mikebridge

+0

См .: http://codepen.io/mikebridge/pen/jyxjwe – mikebridge

1

Это происходит потому, что в тесте # 3 вы передаете его экземпляр: <HelloWorldComponent />, вместо типа/класса HelloWorldComponent. JSX преобразуется в то, что составляет много шаблонов создания объектов.