СереднійstateuseStatecontextreduxzustand

Як працює управління станом в React?

Огляд різних способів управління станом в React додатках

Як працює управління станом в React?

Управління станом - це один з найважливіших аспектів розробки React додатків. Розглянемо різні підходи та їх використання.

Типи стану

1. Локальний стан компонента

Найпростіший тип стану, який належить конкретному компоненту:

function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <span>{count}</span>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  );
}

2. Підняття стану вгору (Lifting State Up)

Коли кілька компонентів потребують доступу до одного стану:

function App() {
  const [user, setUser] = useState(null);
  
  return (
    <div>
      <Header user={user} />
      <Profile user={user} setUser={setUser} />
    </div>
  );
}

Розширені рішення

Context API

Для передачі даних через дерево компонентів без prop drilling:

const UserContext = createContext();

function UserProvider({ children }) {
  const [user, setUser] = useState(null);
  
  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
}

function Profile() {
  const { user, setUser } = useContext(UserContext);
  // ...
}

Кастомні хуки для стану

function useUser() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(false);
  
  const login = async (credentials) => {
    setLoading(true);
    try {
      const userData = await loginAPI(credentials);
      setUser(userData);
    } finally {
      setLoading(false);
    }
  };
  
  return { user, loading, login };
}

Зовнішні бібліотеки

Redux

Для складних додатків з передбачуваним управлінням станом:

// Reducer
function counterReducer(state = { count: 0 }, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    default:
      return state;
  }
}

// Component
function Counter() {
  const count = useSelector(state => state.count);
  const dispatch = useDispatch();
  
  return (
    <button onClick={() => dispatch({ type: 'INCREMENT' })}>
      {count}
    </button>
  );
}

Zustand

Легка альтернатива Redux:

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}));

function Counter() {
  const { count, increment } = useStore();
  return <button onClick={increment}>{count}</button>;
}

Коли використовувати кожен підхід

Локальний стан (useState)

  • Стан належить тільки одному компоненту
  • Прості форми, тогли, локальні UI стани

Context API

  • Дані потрібні багатьом компонентам
  • Теми, мовні налаштування, інформація про користувача

Redux/Zustand

  • Складна логіка оновлення стану
  • Потреба в middleware (логування, async actions)
  • Великі додатки з багатьма взаємопов'язаними станами

Найкращі практики

  1. Починайте з локального стану - не ускладнюйте без потреби
  2. Підіймайте стан тільки коли потрібно - тримайте стан якомога нижче
  3. Використовуйте Context обережно - може призвести до зайвих ре-рендерів
  4. Розділяйте логіку та UI - виносьте бізнес-логіку в кастомні хуки

Правильний вибір підходу до управління станом значно спрощує розробку та підтримку додатка.