React + MySQL: подключение через Node.js API

React напрямую не подключается к MySQL. Браузерный код нельзя пускать в базу данных: логин и пароль окажутся у пользователя. Правильная схема — React делает HTTP-запросы к backend, а backend работает с MySQL.

Архитектура

React в браузере -> HTTP API -> Node.js Express -> MySQL

Создать таблицу

CREATE DATABASE react_app;
USE react_app;

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(150) UNIQUE NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO users (name, email) VALUES
  ('Алиса', 'alice@example.com'),
  ('Боб', 'bob@example.com');

Backend на Express

mkdir backend
cd backend
npm init -y
npm install express mysql2 cors dotenv
const express = require('express');
const mysql = require('mysql2/promise');
const cors = require('cors');
require('dotenv').config();

const app = express();
app.use(cors());
app.use(express.json());

const pool = mysql.createPool({
  host: process.env.DB_HOST || 'localhost',
  user: process.env.DB_USER || 'root',
  password: process.env.DB_PASSWORD || '',
  database: process.env.DB_NAME || 'react_app',
});

app.get('/api/users', async (req, res) => {
  const [rows] = await pool.query('SELECT id, name, email FROM users ORDER BY id DESC');
  res.json(rows);
});

app.post('/api/users', async (req, res) => {
  const { name, email } = req.body;
  const [result] = await pool.query(
    'INSERT INTO users (name, email) VALUES (?, ?)',
    [name, email]
  );
  res.status(201).json({ id: result.insertId, name, email });
});

app.delete('/api/users/:id', async (req, res) => {
  await pool.query('DELETE FROM users WHERE id = ?', [req.params.id]);
  res.json({ ok: true });
});

app.listen(3001, () => {
  console.log('API started on http://localhost:3001');
});

React frontend

import { useEffect, useState } from 'react';

const API = 'http://localhost:3001/api';

function App() {
  const [users, setUsers] = useState([]);
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  async function loadUsers() {
    const response = await fetch(`${API}/users`);
    const data = await response.json();
    setUsers(data);
  }

  useEffect(() => {
    loadUsers();
  }, []);

  async function addUser(event) {
    event.preventDefault();

    await fetch(`${API}/users`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name, email }),
    });

    setName('');
    setEmail('');
    loadUsers();
  }

  return (
    <main>
      <form onSubmit={addUser}>
        <input value={name} onChange={e => setName(e.target.value)} placeholder="Имя" />
        <input value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" />
        <button>Добавить</button>
      </form>

      {users.map(user => (
        <p key={user.id}>{user.name} — {user.email}</p>
      ))}
    </main>
  );
}

Безопасность

  • Не храните пароль MySQL в React-коде.
  • Используйте параметры запроса, а не склейку SQL строк.
  • Проверяйте входные данные на backend.
  • Ограничьте CORS доменом frontend в production.
  • Для авторизации добавьте сессии или JWT на backend.

Добавить обновление пользователя

app.put('/api/users/:id', async (req, res) => {
  const { name, email } = req.body;
  await pool.query(
    'UPDATE users SET name = ?, email = ? WHERE id = ?',
    [name, email, req.params.id]
  );
  res.json({ id: Number(req.params.id), name, email });
});

Файл .env для backend

DB_HOST=localhost
DB_USER=root
DB_PASSWORD=secret
DB_NAME=react_app
PORT=3001

Файл .env должен лежать на backend и не должен попадать в публичный репозиторий. В React-папку эти значения класть нельзя.

Структура production-проекта

В production frontend обычно собирают в статические файлы и отдают через Nginx. Backend запускают отдельным Node.js процессом или контейнером. MySQL находится отдельно, а доступ к нему открыт только backend-серверу.

  • React: npm run build.
  • Nginx: отдаёт dist и проксирует /api.
  • Express: проверяет данные и выполняет SQL.
  • MySQL: недоступен напрямую из браузера.
  • Переменные окружения: только на сервере.

Что важно не перепутать в React + MySQL

Главная ошибка в этой теме — пытаться подключить браузер напрямую к базе. React должен общаться с backend API, а уже backend работает с MySQL. Так вы не раскрываете пароль базы и можете нормально проверять права пользователя.

В учебных примерах это разделение иногда кажется лишним, но в реальном проекте оно обязательно. Backend проверяет права, валидирует входные данные, прячет пароль базы и возвращает frontend только тот JSON, который можно показать пользователю.

Правильная схема

  • React отправляет fetch-запросы на /api;
  • Express проверяет входные данные;
  • backend выполняет SQL через mysql2;
  • пароль MySQL хранится в .env на сервере;
  • браузер никогда не видит доступы к базе.

Что добавить перед production

Минимальный учебный пример не закрывает безопасность полностью. Перед реальным запуском нужны авторизация, валидация данных, ограничение CORS, нормальная обработка ошибок и логирование backend-запросов.

Как развивать пример

После списка пользователей добавьте редактирование, поиск, пагинацию и обработку duplicate email. Эти задачи быстро показывают, зачем нужен backend-слой, а не прямой доступ к MySQL.

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x