34

I've run in some problems add Material UI to my React project, which is programmed with Typescript.

According to the tutorial, I start with adding the react-tab-event-plugin first.

import injectTapEventPlugin from 'react-tap-event-plugin';

// Needed for onTouchTap
// Can go away when react 1.0 release
// Check this repo:
// https://github.com/zilverline/react-tap-event-plugin
injectTapEventPlugin();

Doing this, I get an error about the missing default export.

ERROR in ./src/index.tsx
(4,8): error TS1192: Module ''react-tap-event-plugin'' has no default export.

Adding Material UI

import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

Throws following build error

ERROR in ./src/containers/index.tsx
(8,25): error TS2307: Cannot find module 'material-ui/styles/getMuiTheme'.

ERROR in ./src/containers/index.tsx
(9,30): error TS2307: Cannot find module 'material-ui/styles/MuiThemeProvider'.

My Webpack Config is quite easy and did work with every React npm modul when I added the typings, until now.

var cssnext = require('postcss-cssnext')
var postcssImport = require('postcss-import')
var ExtractTextPlugin = require('extract-text-webpack-plugin')

// noinspection JSUnresolvedVariable
module.exports = {
  entry: {
    app: './src/index.tsx',
    lib: [
      './node_modules/react/react.js',
      './node_modules/react-dom',
      './node_modules/normalize.css/normalize.css'
    ]
  },
  output: {
    path: './dist',
    filename: '[name].js'
  },
  devtool: 'source-map',
  devServer: {
    contentBase: '/dist/',
    inline: true,
    port: 3333,
    host: '0.0.0.0'
  },
  resolve: {
    // Add `.ts` and `.tsx` as a resolvable extension.
    extensions: [ '', '.webpack.js', '.web.js', '.ts', '.tsx', '.js', '.css', '.html' ],
    modulesDirectories: ['src', 'node_modules']
  },
  module: {
    loaders: [
      // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
      { test: /\.ts(x?)$/, loader: 'babel-loader!ts-loader' },
      { test: /\.html$/, loader: 'file?name=[name].[ext]' },
      { test: /\.json$/, loader: 'json' },
      { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader!postcss-loader') }
    ],
    preLoaders: [
      // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
      { test: /\.js$/, loader: 'source-map-loader' }
    ]
    /*    loaders: [
     {
     test: /\.js$/,
     exclude: /node_modules/,
     loader: 'babel-loader!ts-loader',
     query: {
     presets: [
     'es2015',
     'react'
     ]
     }
     }
     ]*/
  },
  plugins: [
    new ExtractTextPlugin('[name].css', {
      allChunks: true
    })
  ],
  postcss: function (webpack) {
    return [
      postcssImport({
        addDependencyTo: webpack
      }),
      cssnext({
        browsers: 'last 2 versions, ie >= 9'
      })
    ]
  }
  // When importing a module whose path matches one of the following, just
  // assume a corresponding global variable exists and use that instead.
  // This is important because it allows us to avoid bundling all of our
  // dependencies, which allows browsers to cache those libraries between builds.
  /*
   externals: {
   'react': 'React',
   'react-dom': 'ReactDOM'
   }
   */
}

Typing for both, react-tap-event-plugin and Material-UI are installed.

What's wrong?

René Stalder
  • 2,536
  • 5
  • 31
  • 50

4 Answers4

51

@types/material-ui is now available, exported from its DefinitelyTyped source.

npm install @types/material-ui --save-dev

npm install @types/react-tap-event-plugin --save-dev

Afterwards, you can do following:

import * as injectTapEventPlugin from 'react-tap-event-plugin';

// Needed for onTouchTap
// Check this repo:
// https://github.com/zilverline/react-tap-event-plugin
injectTapEventPlugin();

Then use Material UI like this:

import * as React from 'react';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import {MuiThemeProvider, lightBaseTheme} from "material-ui/styles";

const lightMuiTheme = getMuiTheme(lightBaseTheme);

class Root extends React.Component<any, any> {
  render() {
    return (
      <MuiThemeProvider muiTheme={lightMuiTheme}>
        <MyComponent/>
      </MuiThemeProvider>
    )
  }
}

The MyComponent would consume Material UI as defined in the docs:

import RaisedButton from 'material-ui/RaisedButton';

const MyComponent = (props:MyComponentProps) => {
  return (
      <RaisedButton label="Default" />
  )
}

export default MyComponent;

2016-08-08: Answer updated due to state change of the package.

2017-01-03: Add ref. to @types /qvazzler

Mahmood
  • 1,069
  • 9
  • 11
René Stalder
  • 2,536
  • 5
  • 31
  • 50
  • most of the links here don't currently work, including the 'typings install...' – Dwight Lisper Jul 20 '16 at 16:50
  • @DwightLisper That's exactly why I wrote “Take care, this might be a temporary branch and it can go in the future.” ;) – René Stalder Aug 08 '16 at 13:14
  • @RenéStalder when i did this, it was always throwing material-ui/styles module not found error. i had to expliclty import 'materialUI' first before importing anything else (import * as mui from 'material-ui';) and that made it work – Hitesh.Aneja Oct 28 '16 at 19:40
  • @Hitesh.Aneja But what you now are doing is, you import every component which might lead to bigger file size and unused garbage (except TypeScript does remove unused imports, I don't know). Also see the documentation of Material UI. With the correct typings you should be able to use the documented way. http://stackoverflow.com/questions/37186500/how-to-setup-material-ui-for-react-with-typescript/37412793?noredirect=1#comment67881451_37412793 – René Stalder Dec 05 '16 at 19:31
  • for me import is working only `import { getMuiTheme } from 'material-ui/styles';` – Anatoli Klamer Jul 27 '17 at 10:11
  • I tried this with the project generated by dotnet new, it does not work, keep telling me null can not convert to object – Chen Aug 17 '17 at 16:28
  • It works for me. I was only missing the style setup. I did not install `@types/react-tap-event-plugin`, and it works fine as a web app. – Jingpeng Wu Sep 05 '17 at 01:07
13

Types are now bundled directly with Material-ui so there is no need to install @types/material-ui package.

Instead you can just install the @material-ui/core package as normal and it should work.

See the official Material-UI + Typescript example with create react app here: https://github.com/mui-org/material-ui/tree/master/examples/create-react-app-with-typescript

bhish
  • 2,289
  • 2
  • 10
  • 9
3

Your comment already pointed out the core problem. The typings are not up-to-date, or in other words: completely off.

Long story short, it seems like the structure of material-ui has changed and everything is camelcase (instead of dashes) and in root, not the lib folder now.

To fix this, open your material-ui/index.d.ts file and start changing everything from

declare module 'material-ui/lib/text-field' {

to

declare module 'material-ui/TextField' {

If unsure, check your node_modules/material-ui folder to see the file structure. The ambient module name must match the underlying file structure.

This probably won't fix all your problems, but it could be a start.

Community
  • 1
  • 1
neo post modern
  • 2,262
  • 18
  • 30
1

Add these two dependencies to your package.json file and run npm install and then start. It worked for me

"@types/material-ui": "^0.21.1", "material-ui": "^0.20.0",