2016-12-14 2 views
1

Я пытаюсь получить доступ к текущим цветам темы в пользовательском компоненте React. Пример, который я использую, относится к материалу UI http://www.material-ui.com/#/customization/themesИспользование Material-UI muiThemeable в машинописном файле

Я пробовал несколько вариантов, но не могу заставить TypScript компилировать мой компонент. Ошибка, которую я получаю, это ... ошибка TS2345: Аргумент типа 'typeof MainHeader' не присваивается параметру типа 'Компонент < {}, {}>'.

import * as React from "react"; 
import muiThemeable from 'material-ui/styles/muiThemeable'; 

interface Properties { 
    title: string 
} 

class MainHeader extends React.Component<Properties, any> { 

render() { 
    return (
    <div className='hero' > 
     <div className='logo' /> 
     <div className="bar" /> 

     <h1>{this.props.title}</h1> 
    </div> 
); 
    } 
} 

export default muiThemeable()(MainHeader); 

ответ

1

мне кажется, определение материально-интерфейс для функции muiThemeable не прав ...

делает

export default muiThemeable()(MainHeader); 

так же, как делают

export const themed = muiThemeable<MainHeader, {}, {}>()(MainHeader) 

и не компилируется, потому что вы пропустили тип свойства компонента и компонент недвижимости состояние

компилятор выводит

<TComponent<P, S>,{}, {}> 

который не соответствует функции ограничения

 export function muiThemeable<TComponent extends (React.Component<P, S>), P, S>() 
      : (component: TComponent) => TComponent; 

... позволяет добавить недостающие Сдерживает

, чтобы удовлетворить компилятор, мы должны сделать

export default (props: Properties) => muiThemeable<MainHeader, Properties, any>()(new MainHeader(props)); 

, но это дает пример функции, когда F ожидает класс

если вы позже сделаете ...

// ...  
import Themeable from "./themeable"; 
let props = { title: "hello!" }; 
ReactDOM.render(<Themeable {...props}/>, document.getElementById("main")); 

он не будет работать

, но если вы измените muiThemeable определение:

export function muiThemeable<TComponent extends (React.Component<P, S>), P, S>() 
     : (component: Function) => TComponent; 

, то вы можете использовать:

export default muiThemeable<MainHeader, Properties, any>()(MainHeader); 

ТСК будет генерировать ошибки

JSX element type 'Themeable' does not have any construct or call signatures 

но это transpile правильно, и работать

, но это не ОК,

потому что:

  • он не строит
  • Функция не описывает правильный параметр тип
  • ни TComponent не описывает, что возвращается,

это выглядит как его возвращение экземпляра, когда нам нужен класс, ... тип

наконец:

эта подпись делает немного больше смысла:

export function muiThemeable<TComponent extends (React.Component<P, S>), P, S>(): (component: new()=> TComponent) => (new() => TComponent); 

, но после того, глядя на source

export function muiThemeable<TComponent extends React.Component<P, S>, P extends MuiThemeProviderProps, S> (Component: new() => TComponent): React.StatelessComponent<P> 

И это может быть способ, чтобы уйти с переписывания или увеличения его определение.
Обертывание функции
... и, возможно, с помощью декоратора, чтобы уменьшить шаблонные и легче читать ...

import * as React from "react"; 
    import * as ReactDOM from "react-dom"; 
    import * as injectTapEventPlugin from "react-tap-event-plugin"; 

    // Needed for onTouchTap 
    // http://stackoverflow.com/a/34015469/988941 
    injectTapEventPlugin(); 


    import darkBaseTheme from "material-ui/styles/baseThemes/darkBaseTheme"; 
    import MuiThemeProvider from "material-ui/styles/MuiThemeProvider"; 
    import getMuiTheme from "material-ui/styles/getMuiTheme"; 
    import muiThemeable from "material-ui/styles/muiThemeable"; 

    import AppBar from "material-ui/AppBar"; 
    import MuiThemeProviderProps = __MaterialUI.Styles.MuiThemeProviderProps; 

    function Themeable<TComponent extends React.Component<P, any>, P extends MuiThemeProviderProps> (Component: new() => TComponent): new() => TComponent { 
     return muiThemeable<TComponent, P, any>()(Component as any) as any; 
    } 

    const themeable = <P, TFunction extends React.ComponentClass<P>>(target: TFunction): TFunction => { 
     return Themeable(target as any) as any; 
    }; 

    export interface MyBarProps extends __MaterialUI.AppBarProps, __MaterialUI.Styles.MuiThemeProviderProps { 
     // ... 
    } 

    @themeable 
    export class MyBar extends React.Component<MyBarProps, any> { 

     constructor(props?: MyBarProps, context?: any) { 
      super(props, context); 
     } 

     render() { 
      if (!this.props.muiTheme) { 
       throw new Error("muiTheme not Found"); 
      } 
      return (
       <AppBar {...this.props} /> 
      ); 
     } 
    } 

    const darkTheme = getMuiTheme(darkBaseTheme); 
    darkTheme.appBar.color = "red"; 

    const Main =() => (
     <MuiThemeProvider muiTheme={darkTheme}> 
      <MyBar title="My AppBar" /> 
     </MuiThemeProvider> 
    ); 

    ReactDOM.render(<Main></Main>,document.getElementById("root")); 
+0

Как именно вы используете это в машинописном? Пробовал делать то же самое, что и OP, но не может найти решение для этого ... Не могли бы вы разместить полный пример того, как один из них использует muiThemeable с TypeScript? –

+0

@ RicardoAmaral посмотрите пожалуйста [это] (https://github.com/D10221/react-mobx-material-ui-rxjs-tedious-sqlserver-node-electron-typescript/blob/master/.vscode/chrome. cmd) помогает, просто загрузил его для вашего удобства :), buena suerte! – Dan

+0

Была ли эта ссылка предназначена для того, чтобы точно указать на этот файл? Просто клонировал весь проект, но не смог найти ссылку на 'muiThemeable' ... Я что-то упустил? –