# Developing Applications with React + Django


<!--more-->

Modern user interfaces in web applications are often built using frameworks like React. The server-side can utilize
various technologies. In this article, we will explore the simplest way to integrate React and Django.

## Installing Django

Create a folder for the future application and navigate into it. Next, create a virtual environment and install the
necessary packages.

```shell
python3 -m venv venv
source venv/bin/activate    # for Linux/Mac
venv\Scripts\activate    # for Windows
pip install django django-rest-framework
```

Create a new Django project, for example, we will call it **backend**.

```shell
django-admin startproject backend
cd backend
```

And create a new application, which we will call **myapi**.

```shell
python manage.py startapp myapi
python manage.py migrate
python manage.py createsuperuser --username $USER --email admin@example.com
```

Save the installed libraries to a `requirements.txt` file and keep it updated. We will need it later for deploying the
application on another developer's computer or a production server.

```shell
pip freeze > requirements.txt
```

Now you can run your application.

```shell
python manage.py runserver
```

At this stage, the admin panel should already be working
at [http://127.0.0.1:8000/admin/](http://127.0.0.1:8000/admin/).

### Adding a Simple API Handler

Let's add our modules to the settings file `backend/settings.py`.

```python
INSTALLED_APPS = [
    ...
    'rest_framework',
    'myapi',
]
```

Also, starting from Django 4.0, we need to specify a list of trusted origins for unsafe requests (e.g., POST).
We will also set the values for STATIC_ROOT and STATIC_URL, as they will be needed during the deployment stage of the 
project.

```python
CSRF_TRUSTED_ORIGINS = ['http://localhost:3000', 'http://127.0.0.1:3000']
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
```

Create a simple handler by writing it in the file `myapi/views.py`. The handler can be written as classes or as separate
functions. We will consider both options.

```python
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import generics


@api_view(['GET'])
def Hello(request):
    if request.method == 'GET':
        data = {'message': 'Hello world!'}
        return Response(data)


class Bye(generics.RetrieveAPIView):
    def get(self, request, *args, **kwargs):
        data = {'message': 'Bye world!'}
        return Response(data)
```

Next, we need to set up the routing. To do this, create a routing file in our module `myapi/urls.py` and define all the
API function calls in it.

```python
from django.urls import path
from myapi import views

urlpatterns = [
    path('hello/', views.Hello),
    path('bye/', views.Bye.as_view()),
]
```

Then, open the main routing file of the application `backend/urls.py` and add paths to our modules.

```python
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('myapi.urls')),
    # You can connect multiple modules with non-overlapping sub-paths to one path
    # path('api/', include('another.urls')),
]
```

If everything is written correctly, you can now check how our API requests work
at [http://127.0.0.1:8000/api/hello/](http://127.0.0.1:8000/api/hello/)
and [http://127.0.0.1:8000/api/bye/](http://127.0.0.1:8000/api/bye/).

Sure! Here’s the translation of the article into English:

## Installing React

Next, you need to choose the installation option: Standard or with Vite.

### Standard React Installation

Let's install React. To do this, navigate to the root directory of our project and start the installation. For this
example, we will use TypeScript.

```shell
cd ..
npx create-react-app frontend --template typescript
```

Since the Django server and the React server are two different servers that do not know about each other, we will proxy
all API requests from the React server to Django. This is simpler and more convenient than setting up cross-origin
requests [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). We edit the `frontend/package.json` file and
add a line indicating the use of a proxy.

```json
{
  "proxy": "http://localhost:8000",
  ...
}
```

Now all external requests will be redirected through this proxy to our Django application. This is convenient because
this setting only affects the development server and does not impact the final application deployed in production.
Additionally, no changes need to be made on the Django server side. You can read more in the
official [documentation](https://create-react-app.dev/docs/proxying-api-requests-in-development/).

Navigate to the **frontend** directory and start the development server.

```shell
cd frontend
npm start
```

The server should start successfully, and the application page will open
at [http://localhost:3000/](http://localhost:3000/).

### Installing React with Vite

If we want to use a more modern development and build system, we can install React with Vite. We will also use
TypeScript. To install regular JavaScript, use the `react` template.

```shell
cd ..
npm create vite@latest frontend -- --template react-ts
```

Let's configure Vite to send requests to our API through a Proxy. Edit `frontend/vite.config.ts`.

```ts
import {defineConfig} from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [react()],
    server: {
        port: 3000,
        proxy: {
            '/api': {
                target: 'http://127.0.0.1:8000',
                changeOrigin: true,
                secure: false,
                ws: true,
            }
        },
    },
})
```

Now let's start the development environment.

```shell
cd frontend
npm install
npm run dev
```

## Installing Tailwind CSS

To create a beautiful, modern user interface, we will use Tailwind CSS. Let's install it.

```shell
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```

Next, we will configure it by editing the `tailwind.config.js` file.

```js
/** @type {import('tailwindcss').Config} */
export default {
    content: [
        "./index.html",
        "./src/**/*.{js,ts,jsx,tsx}",
    ],
    theme: {
        extend: {},
    },
    plugins: [],
}
```

Then, we will connect the Tailwind CSS library to our styles in `src/index.css`. To do this, we clear all the content 
of this file that remains from the template example and write the following:

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

## Simple Application for Testing the API

Let's make a simple API request. Open `src/App.tsx` and replace the old content with this:

```typescript jsx
import {useState} from 'react';

function App() {
    const [url, setUrl] = useState('hello');
    const [message, setMessage] = useState('Wait...');
    const handleClick = () => {
        fetch('/api/' + url)
            .then(response => response.json())
            .then(json => {
                setMessage(json['message']);
                if (url === 'hello')
                    setUrl('bye');
                else
                    setUrl('hello');
            })
            .catch(error => console.error(error));
    };

    return (
        <div className="mx-auto max-w-3xl px-4 sm:px-6 xl:max-w-5xl xl:px-0">
            <button
                className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 mt-4 rounded"
                onClick={handleClick}>
                <pre>{message}</pre>
            </button>
        </div>
    );
}

export default App;
```

If the text does not change when you click the button, make sure that the Django server is also running 
in another window.

As a result, we have created a simple React + Tailwind CSS application with an interface consisting of a single button 
and an API request handler for Django.

In the next article, we will set up a production server with our application in Docker containers and an SSL certificate
for public access in [Deploying React + Django]({{< relref "deploy-react-and-django" >}}).

