Leon Gaban
Leon Gaban

Reputation: 39018

node_modules/@types/react/index"' has no default export

Trying to convert a React app over into Typescript and running into strange errors.

node_modules/@types/react/index"' has no default export.

node_modules/@types/react-dom/index"' has no default export.

I have my tsconfig and webpack setup for typescript. After changing this one component's extension from .js to .tsx I'm getting errors for React?

enter image description here

Thoughts?

tsconfig.json

{
  "compilerOptions": {
    "outDir": "./moonholdings/",
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es5",
    "jsx": "react"
  },
  "include": [
    "./app/**/*"
  ]
}

webpack

/* eslint-disable no-console */
import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import path from 'path';
import chalk from 'chalk';

const moonholdings = path.resolve(__dirname, 'moonholdings');
const app = path.resolve(__dirname, 'app');
const nodeModules = path.resolve(__dirname, 'node_modules');

const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
  template: path.join(__dirname, '/app/index.html'),
  inject: 'body'
});

const ExtractTextPluginConfig = new ExtractTextPlugin({
  filename: 'moonholdings.css',
  disable: false,
  allChunks: true
});

const CopyWebpackPluginConfigOptions = [{
  from: 'app/static',
  to: 'static/'
}];

const CopyWebpackPluginConfig = new CopyWebpackPlugin(CopyWebpackPluginConfigOptions);

const PATHS = {
  app,
  build: moonholdings
};

const LAUNCH_COMMAND = process.env.npm_lifecycle_event;

const isProduction = LAUNCH_COMMAND === 'production';
process.env.BABEL_ENV = LAUNCH_COMMAND;

const productionPlugin = new webpack.DefinePlugin({
  'process.env': {
    NODE_ENV: JSON.stringify('production')
  }
});

const base = {
  // entry: ['babel-polyfill', PATHS.app],
  entry: './app/index.tsx',
  output: {
    path: PATHS.build,
    publicPath: '/',
    filename: 'index_bundle.js'
  },
  resolve: {
    modules: [app, nodeModules],
    extensions: ['.ts', '.tsx', '.js', '.json']
  },
  module: {
    rules: [
      // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
      { test: /\.tsx?$/, loader: 'awesome-typescript-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.s?css/,
        use: [
          'style-loader',
          'css-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)/,
        loader: 'file-loader?name=[path][name].[ext]'
      },
      // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
      { enforce: 'pre', test: /\.js$/, loader: 'source-map-loader' }
    ]
  }
};

const developmentConfig = {
  devtool: 'cheap-module-inline-source-map',
  devServer: {
    contentBase: moonholdings
  },
  plugins: [
    CopyWebpackPluginConfig,
    ExtractTextPluginConfig,
    HtmlWebpackPluginConfig
  ]
};

const productionConfig = {
  devtool: 'cheap-module-source-map',
  plugins: [
    CopyWebpackPluginConfig,
    ExtractTextPluginConfig,
    HtmlWebpackPluginConfig,
    productionPlugin
  ]
};

console.log(`${chalk.magenta('฿')} ${chalk.green('yarn run:')} ${chalk.red(LAUNCH_COMMAND)}`);

export default Object.assign(
  {}, base,
  isProduction === true ? productionConfig : developmentConfig
);

Upvotes: 26

Views: 33029

Answers (5)

Erik Sombroek
Erik Sombroek

Reputation: 165

For any future dev this was caused by the JavaScript and TypeScript Nightly extension for me in visual studio code.

Upvotes: 1

William Nemencha
William Nemencha

Reputation: 11

Add a react-shim.js file at project root with following content:

import * as React from "react";
export { React };

Upvotes: 0

Gustavo Straube
Gustavo Straube

Reputation: 3861

I was having a similar issue while using Next.js and found out it's possible to simply omit the import declaration in this case. A component like the following would have the first line removed.

import React from "react"; // Delete this line

function MyComponent(): JSX.Element {
  return (
    <div>MyComponent</div>
  );
}

export default MyComponent;

It's still possible to import components, hooks, etc. from React if needed, e.g.:

import { useState } from "react";

Notice I already had the options describe in GoalsAndGambles' answer added to my tsconfig.json file.

Upvotes: 1

Ikhlak S.
Ikhlak S.

Reputation: 9034

You can use this syntax by simply adding "allowSyntheticDefaultImports": true and "esModuleInterop":true to your tsconfig.json

{
  ...
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
  },
  ...
}

Upvotes: 56

QoP
QoP

Reputation: 28397

You have to use import * as React from "react"; instead of import React from 'react'.

That happens because babel (the one that you were using before) assumes modules.export as default export while typescript (the one that you are using now) does not.

Upvotes: 42

Related Questions