1

I was following this tutorial and it's been a week I tried to resolve the issue:

SyntaxError: TestComponent.js: Unexpected token (5:6)

  3 |   render() {
  4 |     return (
> 5 |       <div>
    |       ^
  6 |         { this.props.children }
  7 |       </div>
  8 |     )

Currently, we have @babel/preset-env, @babel/preset-react, @babel/cli in 2019 rather than the tutorial pointing to babel-preset-es2015 babel-preset-stage-0 babel-preset-react babel-cli.

So, using them in package.json doesn't solve the issue:

"babel": {
    "presets": [
      "@babel/env",
      "@babel/react"
    ]
  }

I have tried several ways but nothing stopping the error. I hope someone has resolved the issue and can provide a solution.

Greatly appreciated!

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
  • What do you want to achieve? Create a library that uses JSX? You could look into [microbundle](https://github.com/developit/microbundle). – Tholle Mar 26 '19 at 17:37
  • I have seen several ways. But I like the linked tutorial approach which best fit to my requirements. And thus, trying to resolve in that. – Bhojendra Rauniyar Mar 26 '19 at 17:38
  • PS: I'll provide the bounty worth 500 whoever give me the solution. Thanks in advance. – Bhojendra Rauniyar Mar 26 '19 at 17:45
  • Rename your file to `TestComponent.jsx`. Does that help? – smac89 Mar 26 '19 at 17:57
  • @smac89 Doesn't help. – Bhojendra Rauniyar Mar 26 '19 at 17:58
  • I've only ever used jsx with vue and in my package.json, I had to add `"@vue/babel-preset-jsx"` to the babel presets, and since I was using typescript, I also had to add `"jsx": "preserve", "jsxFactory": "h"` to tsconfig. You may need to add [`@babel/preset-react`](https://babeljs.io/docs/en/babel-preset-react) to enable jsx syntax – smac89 Mar 26 '19 at 18:02
  • @smac89 For the same, I have also tried `react-jsx` but couldn't solve the issue – Bhojendra Rauniyar Mar 26 '19 at 18:05

2 Answers2

2

TLDR: Detailed step by step guide

A couple things have changed since the writing of the tutorial namely the following are the breaking changes, unless listed otherwise the other steps in the tutorial are the same:

  1. You will need to download and use the babel-cli in order to get your custom "lib" script command to work:

    npm install --save-dev @babel/cli

  2. You will also need to download and use the @babel/plugin-transform-react-jsx plugin within your custom "lib" script command to compile and transform your React code since Babel 6 and up no longer have any native transforms for React. This is necessary for when you want to share your custom component with only native JavaScript on npmjs for others.

    npm install --save-dev @babel/plugin-transform-react-jsx

  3. Update your "lib" script command to use the babel's JSX transforming plugin listed in step 2:

    "scripts": { "start": "node scripts/start.js", "build": "node scripts/build.js", "lib": "babel --plugins @babel/transform-react-jsx src/node_modules --out-dir lib --copy-files", "test": "node scripts/test.js" },

Note: You also don't need the .babelrc file listed in the tutorial as we will edit the webpack.config.js file to properly transpile JSX later on.

Steps 1 - 3 will allow you to publish and share your component with others, but you will still have to make adjustments for your local development and I will describe those steps below:

  1. For your custom component's package.json remove the .js extension for the "main" entry point as this will cause the following issue. For example, here is my custom component's package.json:

    { "private": true, "name": "YourComponent", "main": "./YourComponent" }

Now if you try to compile and run your application locally, using your custom component, it will throw an error complaining about your custom component's JSX syntax:

SyntaxError: YourComponent.js: Unexpected token (6:6)

  3 |   render() {
  4 |     return (
> 5 |       <div>
    |       ^
  6 |         { this.props.children }
  7 |       </div>
  8 |     )

This is because you need to edit your webpack.config.js file to use the @babel/preset-env and @babel/preset-react babel presets. So you want to add this line:

presets: ['@babel/preset-env', '@babel/preset-react'], to your babel loader for your application's code.

For reference, here is the relevant section of my code (starts on line 329):

            ...
             // Process application JS with Babel.
            // The preset includes JSX, Flow, TypeScript, and some ESnext features.
            {
              test: /\.(js|mjs|jsx|ts|tsx)$/,
              include: paths.appSrc,
              loader: require.resolve('babel-loader'),
              options: {
                customize: require.resolve(
                  'babel-preset-react-app/webpack-overrides'
                ),
                presets: ['@babel/preset-env', '@babel/preset-react'],
                plugins: [
                  [
                    require.resolve('babel-plugin-named-asset-import'),
                    {
                      loaderMap: {
                        svg: {
                          ReactComponent: '@svgr/webpack?-svgo,+ref![path]',
                        },
                      },
                    },
                  ],
                ],
                // This is a feature of `babel-loader` for webpack (not Babel itself).
                // It enables caching results in ./node_modules/.cache/babel-loader/
                // directory for faster rebuilds.
                cacheDirectory: true,
                cacheCompression: isEnvProduction,
                compact: isEnvProduction,
              },
            },
           ...

Now if you run locally it should work: npm run start

Those were the major steps that helped fix my JSX complaint for running locally as well as sharing my custom component with others on npmjs. I created a public git repo with my code and a detailed step by step guide to help others, it can be found here.

Hopefully that helps!

Nathan
  • 7,853
  • 4
  • 27
  • 50
  • Comments are not for extended discussion or debugging sessions; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/190879/discussion-on-answer-by-nathan-wright-cant-use-jsx-after-npm-run-eject). Please make sure that the answer has been [edit]ed to incorporate all relevant information. – Cody Gray - on strike Mar 29 '19 at 00:34
0

Looking at the tutorial and noticing it's using both " and ” (different styles of quotations marks, I don't know the correct language to reference them both properly).

There is a very subtle difference in looks between the two but only one of them will be interpreted correctly, the other will cause an error. The .babelrc in the tutorial is using the wrong style of quotation marks.

If you copied and pasted from the article, check to ensure you are using the correct style of quotes which should be the one closest to the Enter key on your keyboard.

  • No. I didn't copy and paste the things. There's no `TestComponent` in the tutorial. But I did for testing it. – Bhojendra Rauniyar Mar 26 '19 at 20:36
  • Your guess is totally wrong. If that would have been happened, you'll not be seeing jsx error. Please delete your answer. Because, this is really irrelevant to the question. – Bhojendra Rauniyar Mar 26 '19 at 20:36
  • Actually, this is what I've had to do in the past to correct problems in tutorials I've done myself. Sorry for offering a suggestion. Good luck to finding a solution! – sipofwater Mar 26 '19 at 20:47
  • Yeah, agree. But I never copy paste the code. And thank you for trying to help me. – Bhojendra Rauniyar Mar 26 '19 at 20:48