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

Пишется ли проект полностью на Context в React

2.2 Middle🔥 291 комментариев
#React#Архитектура и паттерны

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

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

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

Пишется ли проект полностью на Context в React?

Короткий ответ: НЕТ, это плохая идея. React Context - это инструмент для передачи значений глубоко вложенным компонентам, а не для управления всем состоянием приложения. Это частая ошибка junior-разработчиков.

Чем занимается Context

Context предназначен для:

// 1. Передача глобальных данных
const ThemeContext = React.createContext<"light" | "dark">("light");

// 2. Авторизация и user данные
const AuthContext = React.createContext<User | null>(null);

// 3. Конфигурация приложения
const AppConfigContext = React.createContext<Config>({});

// Использование - просто читаем значение
function Header() {
  const { currentUser } = useContext(AuthContext);
  return <div>{currentUser?.name}</div>;
}

Context хорош для данных которые:

  • Редко меняются (тема, язык, права доступа)
  • Нужны всему приложению
  • Не требуют сложной логики обновления

Когда Context становится проблемой

1. Частые обновления состояния

// ПЛОХО - Context обновляется много раз
const [filters, setFilters] = useState(initialFilters);
const [sortBy, setSortBy] = useState("date");
const [pagination, setPagination] = useState({ page: 1, limit: 10 });

const value = { filters, setFilters, sortBy, setSortBy, pagination, setPagination };

// Каждое изменение вызывает ре-рендер ВСЕХ потребителей Context
// Это медленно!

export const FilterContext = React.createContext(value);

2. Проблемы с производительностью

// Это НЕ оптимально
function FilterProvider({ children }: { children: React.ReactNode }) {
  const [filters, setFilters] = useState({});
  const [items, setItems] = useState([]); // много состояния
  const [loading, setLoading] = useState(false);

  // Каждое изменение любого из этих = ре-рендер всех children
  const value = { filters, setFilters, items, setItems, loading, setLoading };

  return (
    <FilterContext.Provider value={value}>
      {children}
    </FilterContext.Provider>
  );
}

Проблема: если изменилось loading, перерендерятся ВСЕ компоненты которые используют FilterContext, даже если они не используют loading.

3. Сложная логика обновления

// Context не подходит для таких вещей
function useFilters() {
  const [filters, setFilters] = useState({});
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);

  const applyFilters = useCallback(async (newFilters) => {
    setLoading(true);
    try {
      const response = await api.getItems(newFilters);
      // сложная логика
      // нормализация
      // кэширование
      setFilters(newFilters);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, []);

  // Это должно быть в отдельном хуке или state management
}

Правильная архитектура

// 1. Context для глобальных данных
const ThemeContext = React.createContext<Theme>("light");
const AuthContext = React.createContext<User | null>(null);

// 2. Custom hooks для бизнес-логики
function useFilters() {
  const [state, dispatch] = useReducer(filtersReducer, initialState);

  const applyFilters = useCallback((newFilters) => {
    dispatch({ type: "APPLY_FILTERS", payload: newFilters });
  }, []);

  return { state, applyFilters };
}

// 3. State management для сложного состояния
// Используйте: Redux, Zustand, Jotai, Recoil
// (если Context не справляется)

// 4. Local state для компонента
function MyComponent() {
  const [localState, setLocalState] = useState();
  // ...
}

Пример неправильного использования Context

// ПЛОХО - всё состояние в Context
const AppContext = React.createContext<AppState>(initialState);

function AppProvider({ children }: { children: React.ReactNode }) {
  const [users, setUsers] = useState([]);
  const [posts, setPosts] = useState([]);
  const [comments, setComments] = useState([]);
  const [notifications, setNotifications] = useState([]);
  const [filters, setFilters] = useState({});
  const [sortBy, setSortBy] = useState("date");
  const [currentUser, setCurrentUser] = useState(null);
  const [theme, setTheme] = useState("light");
  // ... ещё 20 переменных

  // Когда что-то меняется - ВСЁ перерендерится
  const value = { /* огромный объект */ };

  return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
}

Правильное использование Context

// ХОРОШО - разделили по смыслу

// 1. Авторизация - редко меняется
const AuthContext = React.createContext<AuthState>(initialAuth);

function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // загружаем user один раз при mount
    fetchCurrentUser();
  }, []);

  return (
    <AuthContext.Provider value={{ user, loading }}>
      {children}
    </AuthContext.Provider>
  );
}

// 2. Тема - редко меняется
const ThemeContext = React.createContext<"light" | "dark">("light");

function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState<"light" | "dark">("light");

  return (
    <ThemeContext.Provider value={theme}>
      {children}
    </ThemeContext.Provider>
  );
}

// 3. Данные списка - часто меняются
// используем useReducer или state management
function usePostsList() {
  const [state, dispatch] = useReducer(reducer, initialState);

  const fetchPosts = useCallback((filters) => {
    dispatch({ type: "LOADING" });
    api.getPosts(filters).then(data => {
      dispatch({ type: "SUCCESS", payload: data });
    });
  }, []);

  return { ...state, fetchPosts };
}

Когда нужен настоящий State Management

Используйте Redux, Zustand или подобные когда:

// 1. Много состояния которое часто меняется
const store = createStore({
  filters: {},
  sortBy: "date",
  items: [],
  selectedIds: [],
  // ...
});

// 2. Сложная логика обновления
store.on("APPLY_FILTERS", (newFilters) => {
  // валидация
  // кэширование
  // отправка на сервер
});

// 3. Нужна история изменений (undo/redo)
store.undo();
store.redo();

// 4. Нужна отладка и time-travel
devTools.inspect();

Лучшая практика структуры

// Project structure
src/
  contexts/
    AuthContext.tsx      // только авторизация
    ThemeContext.tsx     // только тема
  hooks/
    useFilters.ts        // бизнес-логика фильтров
    usePostsList.ts      // логика списка
    useAuth.ts           // обёртка над AuthContext
  store/                 // если нужен Redux/Zustand
    store.ts
    slices/
  components/
    // используют hooks и Context по необходимости

Итоговый совет

Context - это НЕ state management, это инструмент для пробрасывания значений вниз по дереву. Если вы используете Context для всего состояния, у вас будут проблемы с производительностью и поддерживаемостью.

За Context оставьте:

  • Авторизация
  • Тема
  • Язык
  • Права доступа
  • Глобальные конфиги

Для всего остального используйте hooks и local state, или настоящий state management если состояние сложное.