Бывают ли state manager только глобальными
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Бывают ли state manager только глобальными?
Ответ: НЕТ. State manager может быть локальным, глобальным или гибридным. Давайте разберёмся в разных подходах.
Типы state manager
1. Локальный (Local) state Состояние живёт в одном компоненте:
function Counter() {
const [count, setCount] = useState(0); // локальный state
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}
2. Компонентный (Component tree) state Состояние передаётся через props в дереве компонентов:
function Parent() {
const [user, setUser] = useState(null);
return (
<div>
<Child user={user} onUserChange={setUser} />
<Sibling user={user} />
</div>
);
}
3. Контекстный (Context) state Состояние доступно всем компонентам в Provider'е:
const UserContext = createContext();
function App() {
const [user, setUser] = useState(null);
return (
<UserContext.Provider value={{ user, setUser }}>
<Header />
<Main />
<Footer />
</UserContext.Provider>
);
}
function Header() {
const { user } = useContext(UserContext); // доступно везде
}
4. Глобальный (Global) state Единое хранилище для всего приложения:
// Redux, Zustand, MobX
const store = createStore({ user: null, settings: {} });
app.use(store); // доступно везде в приложении
Сравнение подходов
| Тип | Область | Производительность | Сложность | Использование |
|---|---|---|---|---|
| Local state | Компонент | Отлично | Минимальная | useState для UI |
| Component tree | Поддерево | Хорошо | Малая | Props drilling |
| Context | Provider | OK | Средняя | Глобальные настройки |
| Global | Всё приложение | OK | Большая | Сложное состояние |
Локальные state manager
Использование local state правильно:
// Хорошо - локальное состояние для UI
function Accordion() {
const [isOpen, setIsOpen] = useState(false); // только для этого компонента
return (
<div>
<button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
{isOpen && <Content />}
</div>
);
}
// Хорошо - форма обновляется локально
function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async () => {
await api.login(email, password);
};
return (
<form onSubmit={handleSubmit}>
<input value={email} onChange={(e) => setEmail(e.target.value)} />
<input value={password} onChange={(e) => setPassword(e.target.value)} />
<button type="submit">Login</button>
</form>
);
}
Миксированный подход
Лучший способ - использовать оба:
// Global state - для данных приложения
const useAuth = () => useContext(AuthContext); // user, permissions
// Local state - для UI
function Modal() {
const [isOpen, setIsOpen] = useState(false); // только для модала
const { user } = useAuth(); // глобальные данные
return (
<dialog open={isOpen}>
<p>Hello, {user?.name}</p>
<button onClick={() => setIsOpen(false)}>Close</button>
</dialog>
);
}
Примеры правильного использования
Локальный state:
// Toggle, accordion, modal, form input, loading state
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [selectedTab, setSelectedTab] = useState('tab1');
const [formData, setFormData] = useState({ name: '', email: '' });
Глобальный state:
// Authenticated user, app theme, language, permissions
const { user, theme, language, permissions } = useAppState();
Типы state managers
1. React Context (встроенный)
const ThemeContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
2. Zustand (простой и легкий)
const useStore = create((set) => ({
user: null,
setUser: (user) => set({ user }),
}));
function App() {
const { user, setUser } = useStore();
}
3. Redux (полнофункциональный)
const store = configureStore({
reducer: {
user: userReducer,
settings: settingsReducer,
},
});
function App() {
const user = useSelector(state => state.user);
const dispatch = useDispatch();
}
4. MobX (reactive)
class UserStore {
user = null;
setUser(user) {
this.user = user;
}
}
const userStore = new UserStore();
Как выбрать?
Используй local state если:
- Состояние нужно только одному компоненту
- Состояние меняется часто (но влияет на один компонент)
- Это UI состояние (isOpen, selectedTab, formData)
// Идеально для local state
function SearchBox() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
return (
<div>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
{loading && <Spinner />}
{results.map(item => <Item key={item.id} {...item} />)}
</div>
);
}
Используй Context если:
- Состояние нужно нескольким компонентам
- Состояние редко меняется (theme, language)
- Нет глубокого nesting (prop drilling)
// Идеально для Context
const LanguageContext = createContext();
function LanguageProvider({ children }) {
const [language, setLanguage] = useState('en');
return (
<LanguageContext.Provider value={{ language, setLanguage }}>
{children}
</LanguageContext.Provider>
);
}
Используй global state если:
- Состояние нужно везде в приложении
- Состояние часто меняется (очень активно используется)
- Нужна сложная логика обновления (reducers)
// Идеально для global state (Zustand, Redux)
const useAppStore = create((set) => ({
user: null,
notifications: [],
setUser: (user) => set({ user }),
addNotification: (notif) => set((state) => ({
notifications: [...state.notifications, notif]
})),
}));
Анти-паттерны
Не делай так:
// Плохо - всё в global state
const useStore = create(set => ({
isMenuOpen: false, // это локальное UI
selectedFormTab: 'tab1', // это локальное UI
user: null, // это глобальное
permissions: [], // это глобальное
}));
// Хорошо - разделение
function Menu() {
const [isOpen, setIsOpen] = useState(false); // локальное
}
const useAppStore = create(set => ({
user: null,
permissions: [],
}));
Оптимизация производительности
Local state - лучше для производительности:
// Плохо - весь компонент перерендерится
const [count, setCount] = useState(0); // в global state
// Хорошо - только этот компонент
function Counter() {
const [count, setCount] = useState(0); // local state
}
Context - может быть медленным:
// Плохо - весь Provider перерендерится
const ThemeContext = createContext();
function ThemeProvider() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{/* Всё перерендерится при изменении theme */}
</ThemeContext.Provider>
);
}
// Хорошо - разделить Context
const ThemeValueContext = createContext();
const ThemeActionsContext = createContext();
Итог
State manager НЕ только глобальный:
- Local state - для одного компонента (useState)
- Props - для соседних компонентов (props drilling)
- Context - для поддерева компонентов (глобальные настройки)
- Global state - для всего приложения (Redux, Zustand)
Правило: используй самый простой уровень, который подходит для твоего сценария. Начинай с local state, поднимайся выше только если нужно.
local state (useState)
↓
props (prop drilling)
↓
Context API (глобальные настройки)
↓
Global store (сложное состояние)