eug100
eug100

Reputation: 189

How add javascript files to Visual Studio Community 2019 typescript project

I found some tutorial that explains how to build the simplest project: Tutorial: Create a Node.js and React app in Visual Studio

I succeeded to build a project that shows a message "Welcome to React!!". This project contains only one file in TypeScript: app.tsx. Now I want to build a project containing some additional modules written in React and having extension ".js". It seems that these files should be transpiled to TypeScript. But I did not find how to do that in this project. For example in app.tsx there is a code

import Button from "./Button";
...
ReactDOM.render(<Button />, document.getElementById('root'));

and I have file Button.js that contains

...
handleClick = () => {
this.props.clickHandler(this.props.name);
};

When I run in command line

node_modules\.bin\webpack app.tsx --config webpack-config.js

I get an error message:

ERROR in ./Button.js 11:14
Module parse failed: Unexpected token (11:14)
You may need an appropriate loader to handle this file type, 
currently no loaders are configured to process this file. See 
https://webpack.js.org/concepts#loaders
|   //};
|
>   handleClick = () => {
|     this.props.clickHandler(this.props.name);
|   };

In npm folder I have ts-loader, so I do not understand what the problem? Update 1. I did changes as Rich N suggested and now it works. But I still want to use the original content of Button.js:

import React from "react";
import PropTypes from "prop-types";
//import "./Button.css";

export default class Button extends React.Component {
static propTypes = {
name: PropTypes.string,    
clickHandler: PropTypes.func,
};

handleClick = () => {
this.props.clickHandler(this.props.name);
};

setImage= () => {
  var img="./Images/";
 switch(this.props.name)
 {
   case "move":
       img+="Move.jpg";
       break;
    case "drawPoint":
       img+="Point.jpg";
       break;
       default:
           console.log("default image")
 }
 return img;
 };

 render() {


 return (
  <div >
    <button onClick={this.handleClick}>
        <img src={this.setImage()} alt=""></img>
   </button>
  </div>
  );
  }
 }

When I try to run the project I receive a number of error messages. For example:

Error   TS2339  (TS) Property 'props' does not exist on type 'Button'.

I think this is because not each JavaScript code is valid TypeScript code. So I still have 2 questions:

  1. How change this code so that it will be right TypeScript code?
  2. Is there any utility that allows to do that automatically, not manually?

Upvotes: 0

Views: 126

Answers (1)

Rich N
Rich N

Reputation: 9485

You're right, if you just want to use this code trying to do it in a TypeScript project is a pain. You either need to make some changes so props and its children are properly typed for TypeScript, or change the imports so they're not typed. Working to make the props properly typed seems pointless since the code is already using prop-types to type them.

However, changing the imports isn't actually too hard. Just create Button.tsx with your Button.js code as in my original answer, and then replace the import React from "React" and import PropTypes from "prop-types" statements with the code below. You'll see this makes React and PropTypes of type 'any' if you hover over them, and means TypeScript won't try type-checking everything.

declare var require: any
var React = require('react');
var PropTypes = require('prop-types');

Note that you need the npm package prop-types installed for this to work. If I do that I can display the button with the code below in app.tsx:

ReactDOM.render(<Button name="move"
    clickHandler={(x) => alert('Move')} />, document.getElementById('root'));

Whether you'll have other problems with TypeScript isn't clear though. A better alternative may be to turn this into a JavaScript project. To that you need to change the .tsx files to .jsx and to use a Babel loader in the Webpack config to compile them. If you want to do this I can explain how in more detail: I actually did it as an exercise just now so I have working code.

There's no utility to do this automatically, in answer to your second question.

I'm leaving my original answer below.

ORIGINAL ANSWER

I struggled a bit to work out what you're doing here. However, it looks like you are trying to create a React 'Button' component in a plain .js file in the tutorial example. This isn't going to work. The tutorial has set up Webpack to transpile TypeScript to JavaScript, and a React component therefore needs to be in a .tsx file.

The steps below will get you to a Button component that works:

  • Rename Button.js to Button.tsx
  • Then change the code to:

Button.tsx

declare var require: any
var React = require('react');

var buttonStyle = { background: 'red' };

export default class Button extends React.Component {
    render() {
        return (
        <button
            style = { buttonStyle }
            onClick = { this.props.handleClick } > { this.props.label }</button>
            );
    }
}

app.tsx

declare var require: any
import Button from "./Button";
var React = require('react');
var ReactDOM = require('react-dom');

//export class Hello extends React.Component {
//    render() {
//        return (
//            <h1>Welcome to React!!</h1>
//        );
//    }
//}

//ReactDOM.render(<Hello />, document.getElementById('root'));
ReactDOM.render(<Button label="Click Me"
    handleClick={() => alert('Hello')} />, document.getElementById('root'));

By the way, it would help if you included all your code in your questions so we can easily see what your problem is. In this case all you need to show is app.tsx and Button.js, and we'd have a minimal reproducible example.

Upvotes: 1

Related Questions