Библиотека MUI (Material-UI) предоставляет богатый набор компонентов для React, многие из которых требуют управления состоянием для интерактивного поведения. В MUI управление состоянием чаще всего строится вокруг стандартных подходов React, таких как useState, useReducer, контексты (Context API), а также интеграция с внешними библиотеками управления состоянием (Redux, Zustand, Recoil).
Большинство компонентов MUI управляют своим состоянием через props, но для сложной логики чаще всего используется локальное состояние с React. Пример:
import React, { useState } from 'react';
import { Switch, FormControlLabel } from '@mui/material';
function ToggleExample() {
const [checked, setChecked] = useState(false);
const handleChange = (event) => {
setChecked(event.target.checked);
};
return (
<FormControlLabel
control={<Switch checked={checked} onCha nge={handleChange} />}
label="Включено"
/>
);
}
В этом примере состояние checked полностью контролируется React, а MUI компонент лишь визуализирует текущее значение и вызывает обратный вызов onChange.
Компоненты MUI делятся на контролируемые и неконтролируемые:
TextField с prop value.Checkbox без props checked.<TextField
value={textValue} // контролируемый компонент
onCha nge={(e) => setTextValue(e.target.value)}
/>
<Checkbox defaultChecked /> // неконтролируемый компонент
Контролируемые компоненты позволяют полностью синхронизировать UI с состоянием приложения, что важно для сложных форм и динамических интерфейсов.
Для сложных форм MUI удобно комбинировать useState или useReducer:
import React, { useReducer } from 'react';
import { TextField, Button } from '@mui/material';
const initialState = { username: '', email: '' };
function reducer(state, action) {
switch (action.type) {
case 'SET_FIELD':
return { ...state, [action.field]: action.value };
case 'RESET':
return initialState;
default:
return state;
}
}
function FormExample() {
const [state, dispatch] = useReducer(reducer, initialState);
const handleChange = (field) => (event) => {
dispatch({ type: 'SET_FIELD', field, value: event.target.value });
};
return (
<form>
<TextField label="Username" value={state.username} onCha nge={handleChange('username')} />
<TextField label="Email" value={state.email} onCha nge={handleChange('email')} />
<Button onCl ick={() => dispatch({ type: 'RESET' })}>Сброс</Button>
</form>
);
}
Использование useReducer удобно для форм с большим количеством полей, так как позволяет централизовать логику обновления состояния.
MUI компоненты могут использоваться с React Context для глобального состояния темы, управления модальными окнами или таблицами. Пример темы:
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { CssBaseline, Button } from '@mui/material';
import React, { useState } from 'react';
const lightTheme = createTheme({ palette: { mode: 'light' } });
const darkTheme = createTheme({ palette: { mode: 'dark' } });
function App() {
const [darkMode, setDarkMode] = useState(false);
return (
<ThemeProvider theme={darkMode ? darkTheme : lightTheme}>
<CssBaseline />
<Button onCl ick={() => setDarkMode(!darkMode)}>Переключить тему</Button>
</ThemeProvider>
);
}
В этом случае состояние darkMode управляется на
уровне приложения и передается через контекст MUI
ThemeProvider.
Компоненты, такие как Dialog, Snackbar или
Drawer, активно используют локальное состояние для
отображения и скрытия. Пример с Dialog:
import React, { useState } from 'react';
import { Dialog, DialogTitle, Button } from '@mui/material';
function DialogExample() {
const [open, setOpen] = useState(false);
return (
<>
<Button onCl ick={() => setOpen(true)}>Открыть диалог</Button>
<Dialog open={open} onCl ose={() => setOpen(false)}>
<DialogTitle>Пример модального окна</DialogTitle>
</Dialog>
</>
);
}
Состояние open полностью контролирует отображение модального окна, а MUI управляет анимацией и фокусом.
Для больших проектов MUI интегрируется с Redux, Zustand, Recoil и другими:
import { useSelector, useDispatch } from 'react-redux';
import { increment } from './counterSlice';
import { Button, Typography } from '@mui/material';
function Counter() {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<>
<Typography variant="h4">{count}</Typography>
<Button onCl ick={() => dispatch(increment())}>Увеличить</Button>
</>
);
}
MUI компоненты в этом случае становятся полностью controlled, получая состояние и действия из глобального стор.
useState и
useReducer для небольших компонентов и форм.Эффективное управление состоянием позволяет создавать динамичные и отзывчивые интерфейсы на базе MUI, обеспечивая гибкость и согласованность пользовательского опыта.