2017-02-03 48 views
2

我在TypeScript中有一個React HOC,但當我從TSX組件render方法中調用它時似乎不起作用。這裏有一個例子:我可以直接從React中的JSX/TSX內部調用HOC嗎?

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

第一和第二測試按預期工作---文字是在第二個紅色。但第三行不會呈現任何內容。我預計第二和第三行是一樣的。

當我使用調試器對其進行檢查時,測試#2的參數是HelloWorldComponent類型的組件,但測試#3看到Component = Object {$$typeof: Symbol(react.element), ...}

有沒有一種方法可以從JSX/TSX文件中動態地包裝一個類似{ withRedText(<HelloWorldComponent />) }的語法的組件?

(打字稿2.1.4 &陣營15.4.0)

Here it is on CodePen

+0

這是JavaScript的版本:http://codepen.io/mikebridge/pen/mRLvRd – mikebridge

回答

1

我不認爲你可以直接/隱式地從JSX調用HOC。考慮到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被轉化爲相當於大量對象實例化樣板的東西。

相關問題