← Назад к вопросам

Работает ли Redux без React

2.0 Middle🔥 91 комментариев
#Node.js и JavaScript#Фреймворки и библиотеки

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Redux как независимая библиотека: работает ли без React

Да, Redux полностью работает независимо от React. Это важное понимание, потому что многие разработчики ассоциируют Redux только с React, но на самом деле это две отдельные библиотеки с разными зонами ответственности.

Архитектура Redux

Redux — это паттерн управления состоянием, реализованный как отдельная библиотека. Она состоит из трёх ключевых компонентов:

// 1. Actions — объекты с описанием событий
const incrementAction = {
  type: 'INCREMENT',
  payload: 5
};

// 2. Reducers — чистые функции, преобразующие состояние
const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + action.payload;
    case 'DECREMENT':
      return state - action.payload;
    default:
      return state;
  }
};

// 3. Store — хранилище состояния (из Redux, не из React)
import { createStore } from 'redux';

const store = createStore(counterReducer);

// Это всё работает БЕЗ React!
store.dispatch({ type: 'INCREMENT', payload: 5 });
console.log(store.getState()); // 5

Использование Redux в Node.js Backend

Redux полезен в бэкенде для управления состоянием приложения, особенно в сложных сценариях:

import { createStore, combineReducers } from 'redux';

// Reducers для различных частей состояния
const usersReducer = (state = [], action) => {
  switch (action.type) {
    case 'ADD_USER':
      return [...state, action.payload];
    case 'REMOVE_USER':
      return state.filter(user => user.id !== action.payload);
    default:
      return state;
  }
};

const settingsReducer = (state = {}, action) => {
  switch (action.type) {
    case 'UPDATE_SETTING':
      return { ...state, [action.key]: action.value };
    default:
      return state;
  }
};

// Комбинируем reducers
const rootReducer = combineReducers({
  users: usersReducer,
  settings: settingsReducer
});

const store = createStore(rootReducer);

// Используем в бэкенде
store.dispatch({ 
  type: 'ADD_USER', 
  payload: { id: 1, name: 'Alice' } 
});

store.dispatch({
  type: 'UPDATE_SETTING',
  key: 'apiVersion',
  value: 'v2'
});

console.log(store.getState());
// {
//   users: [{ id: 1, name: 'Alice' }],
//   settings: { apiVersion: 'v2' }
// }

Redux Middleware в бэкенде

Middleware позволяет перехватывать actions и выполнять побочные эффекты:

import { createStore, applyMiddleware } from 'redux';

// Логирование middleware
const loggerMiddleware = store => next => action => {
  console.log('Dispatching:', action);
  const result = next(action);
  console.log('New state:', store.getState());
  return result;
};

// Асинхронный middleware (как redux-thunk)
const asyncMiddleware = store => next => action => {
  if (typeof action === 'function') {
    return action(store.dispatch, store.getState);
  }
  return next(action);
};

const store = createStore(
  counterReducer,
  applyMiddleware(loggerMiddleware, asyncMiddleware)
);

// Асинхронная операция через thunk
const fetchUserThunk = (userId) => (dispatch, getState) => {
  dispatch({ type: 'FETCH_USER_START' });
  
  // Асинхронный API вызов
  fetch(`/api/users/${userId}`)
    .then(res => res.json())
    .then(user => {
      dispatch({ type: 'FETCH_USER_SUCCESS', payload: user });
    })
    .catch(error => {
      dispatch({ type: 'FETCH_USER_ERROR', payload: error });
    });
};

store.dispatch(fetchUserThunk(123));

Redux в Express приложении

Практический пример использования Redux для управления состоянием сервера:

import express from 'express';
import { createStore, combineReducers, applyMiddleware } from 'redux';

const app = express();

// State shape
const appState = {
  activeConnections: 0,
  queuedTasks: [],
  cacheStats: {}
};

// Reducers
const connectionsReducer = (state = 0, action) => {
  switch (action.type) {
    case 'CONNECTION_OPENED':
      return state + 1;
    case 'CONNECTION_CLOSED':
      return Math.max(0, state - 1);
    default:
      return state;
  }
};

const tasksReducer = (state = [], action) => {
  switch (action.type) {
    case 'TASK_QUEUED':
      return [...state, action.payload];
    case 'TASK_COMPLETED':
      return state.filter(t => t.id !== action.payload);
    default:
      return state;
  }
};

const store = createStore(
  combineReducers({
    activeConnections: connectionsReducer,
    queuedTasks: tasksReducer
  })
);

// Используем store в middleware Express
app.use((req, res, next) => {
  store.dispatch({ type: 'CONNECTION_OPENED' });
  
  res.on('finish', () => {
    store.dispatch({ type: 'CONNECTION_CLOSED' });
  });
  
  next();
});

app.post('/tasks', (req, res) => {
  const task = { id: Date.now(), ...req.body };
  store.dispatch({ type: 'TASK_QUEUED', payload: task });
  res.json({ taskId: task.id });
});

app.get('/status', (req, res) => {
  res.json(store.getState());
});

Когда Redux полезен вне React

  • CLI приложения — управление состоянием в interactive shell
  • WebSocket серверы — отслеживание подключений и сессий
  • Job queues — управление состоянием background tasks
  • State machines — сложная логика переходов между состояниями
  • Event sourcing — воспроизведение истории событий

Redux vs. другие подходы в Node.js

// Redux: хорошо для сложного, предсказуемого состояния
const store = createStore(reducer);
store.dispatch(action);

// EventEmitter: хорошо для простых событий
const emitter = new EventEmitter();
emitter.on('event', handler);
emitter.emit('event');

// State machine (XState): хорошо для явных переходов
const machine = createMachine({...});

Заключение

Redux — это полностью независимая от React библиотека для управления состоянием. React Router позволяет подписываться на изменения состояния через react-redux, но сам Redux работает в любой JavaScript среде, включая Node.js серверы. Ключевое преимущество — предсказуемость, отладка через time-travel debugging и простота тестирования.

Работает ли Redux без React | PrepBro