Create React App abstracts away the complexity of configuring a React development environment. It uses tools like Webpack for bundling, Babel for transpiling, and ESLint for linting. When you run npx create - react - app my - app
, it creates a directory structure with all the necessary files and dependencies for a basic React application.
Express is a lightweight web application framework for Node.js. It allows you to create servers, handle HTTP requests (GET, POST, PUT, DELETE, etc.), and manage middleware. Middleware functions in Express are functions that have access to the request object (req
), the response object (res
), and the next middleware function in the application’s request - response cycle.
TypeScript adds static types to JavaScript. This means that you can define the types of variables, function parameters, and return values. For example, instead of just having a variable let num
, you can have let num: number = 10
. Static typing helps catch errors early in the development process and makes the codebase more self - documenting.
First, create a new React application with TypeScript support:
npx create-react-app my-app --template typescript
cd my-app
Create a new directory named server
in the root of your project. Navigate to this directory and initialize a new Node.js project:
mkdir server
cd server
npm init -y
Install Express and TypeScript dependencies:
npm install express
npm install --save-dev typescript @types/express @types/node
Create a tsconfig.json
file in the server
directory with the following basic configuration:
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Create a src
directory in the server
directory and inside it, create a index.ts
file:
import express from 'express';
const app = express();
const port = 3001;
app.get('/', (req, res) => {
res.send('Hello from the Express server!');
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
In the package.json
file of the server
directory, add the following scripts:
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}
}
In the package.json
file of the React application (in the root directory), add the following line to proxy requests to the Express server:
{
"proxy": "http://localhost:3001"
}
In your React components, you can use the fetch
API or a library like axios
to make requests to the Express server. Here is an example of using fetch
in a TypeScript React component:
import React, { useEffect, useState } from 'react';
const App: React.FC = () => {
const [data, setData] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('/');
const text = await response.text();
setData(text);
} catch (error) {
console.error('Error fetching data:', error);
}
};
fetchData();
}, []);
return (
<div>
{data ? <p>{data}</p> : <p>Loading...</p>}
</div>
);
};
export default App;
In the index.ts
file of the Express server, you can handle POST requests. First, you need to parse the incoming JSON data using express.json()
middleware:
import express from 'express';
const app = express();
const port = 3001;
app.use(express.json());
app.post('/data', (req, res) => {
const data = req.body;
console.log('Received data:', data);
res.send('Data received successfully');
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
In Express, it’s important to handle errors properly. You can create an error - handling middleware function:
app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
console.error('Error:', err);
res.status(500).send('Internal Server Error');
});
In React, you can use try...catch
blocks when making API calls to handle errors gracefully.
Use environment variables to store sensitive information like API keys, database connection strings, etc. In the Express server, you can use the dotenv
package:
npm install dotenv
Create a .env
file in the server
directory and add your variables:
API_KEY=your_api_key
In your index.ts
file, load the environment variables:
import dotenv from 'dotenv';
dotenv.config();
const apiKey = process.env.API_KEY;
In React, use code splitting techniques to reduce the initial bundle size. React.lazy and Suspense are great features for this purpose. For example:
const LazyComponent = React.lazy(() => import('./LazyComponent'));
const App: React.FC = () => {
return (
<div>
<React.Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</React.Suspense>
</div>
);
};
In both the React and Express parts of your application, use interfaces to define the structure of data. For example, if you have a User
object in your application:
interface User {
id: number;
name: string;
email: string;
}
You can then use this interface when defining function parameters or return values.
Write unit tests for both the React components and the Express routes. For React, you can use Jest and React Testing Library. For Express, you can use tools like supertest
to test your API endpoints.
Combining Create React App, Express, and TypeScript is a powerful way to build full - stack applications. Create React App simplifies the front - end development process, Express provides a flexible server - side framework, and TypeScript adds type safety to the entire codebase. By following the concepts, usage methods, common practices, and best practices outlined in this blog post, you can create robust and maintainable full - stack applications.