React allows us to write JavaScript code in the standard .js files along with TypeScript in the .ts files, but if you’ve created either a TypeScript or JavaScript React app using yarn’s create command, i.e.
yarn create react-app my-app
you’ll notice .jsx or .tsx files. These are similar to Razor, ASP/ASP.NET, JSP and the likes in that they allow us to embed XML (or strictly speaking in our usage XHTML) into source code.
Let’s look at a React component (I’ll use TypeScript in this example but JavaScript jsx components are much the same), in our App.tsx we might want to include our own tag/element, for example
<HelloMessage name="PutridParrot" />
Yes, we’re always obsessed with the Hello World example and this one’s no different.
The above doesn’t really give any context, so here’s the whole of the App.tdx file
import React, { Component } from 'react';
import './App.css';
import HelloMessage from "./components/HelloMessage";
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<HelloMessage name="Mark" />
</header>
</div>
);
}
}
export default App;
Now the HelloMessage element is a React component. In this example I’ve created a components folder off of the src folder and created the file named HelloMessage.tsx, let’s look at the code for this component and then discuss how it works, here’s the code
import React, { Component } from 'react';
export interface HelloMessageProps {name: string;}
class HelloMessage extends Component<HelloMessageProps, {}> {
render() {
return (
<div>
Hello World {this.props.name}
</div>
);
}
}
export default HelloMessage;
In this example we’ve imported React, hence need not type React.Component, see Import Declarations for more information on this syntax.
Next up, we’ve created and exported an interface. This acts as the shape of the data that the Component expects to see. As TypeScript supports duck typing, we’re basically saying we expect a thing that looks like HelloMessageProps (i.e. has a name of type string) to be passed into the component. This is our attribute list from the example in App.tsx.
The HelloMessage class extends/inherits from Component and we tell it what data shape we expect to be passed into it, but we do not want to pass any state hence we have a second generic parameter of {}. As we’re writing this as a .tsx we’ve embedded the XHTML along with the use of the property name passed as an attribute in the App.tsx. The render method simply returns the embedded XHTML and that’s it.
We can write the same thing without using the embedded syntax, like this
import React, { Component } from 'react';
export interface HelloMessageProps {name: string;}
class HelloMessage extends Component<HelloMessageProps, {}> {
render() {
return React.createElement('div', null, 'Hello World ' + this.props.name);
}
}
export default HelloMessage;
Or better still we can use string interpolation by using the ` (back tick), i.e. replacing the Hello World string section with
`Hello World ${this.props.name}`
References
TypeScript specification
React without JSX