MUI (Material-UI) предоставляет мощные компоненты для построения интерактивных интерфейсов, где пользователи делают выбор через элементы формы: чекбоксы, радиокнопки, селекты, переключатели. Чтобы сохранить выбор пользователя между сессиями или при навигации по приложению, важно правильно работать с состоянием компонентов и интегрировать его с хранилищем данных.
Контролируемые компоненты MUI позволяют полностью управлять их
состоянием через React useState или глобальные состояния
(Redux, Zustand, Recoil). Пример с чекбоксом:
import React, { useState } from 'react';
import Checkbox from '@mui/material/Checkbox';
import FormControlLabel from '@mui/material/FormControlLabel';
function Preferences() {
const [checked, setChecked] = useState(false);
const handleChange = (event) => {
setChecked(event.target.checked);
localStorage.setItem('userPreference', event.target.checked);
};
React.useEffect(() => {
const saved = localStorage.getItem('userPreference') === 'true';
setChecked(saved);
}, []);
return (
<FormControlLabel
control={<Checkbox checked={checked} onCha nge={handleChange} />}
label="Включить уведомления"
/>
);
}
Ключевые моменты:
checked управляется через состояние компонента
(useState).localStorage позволяет восстановить выбор
при следующей загрузке страницы.useEffect используется для инициализации состояния из
хранилища.MUI Select поддерживает как одиночный, так и
множественный выбор. Для сохранения пользовательского выбора логика
схожа с чекбоксами, но нужно учитывать массив значений.
import React, { useState, useEffect } from 'react';
import Sel ect from '@mui/material/Sel ect';
import MenuItem fr om '@mui/material/MenuItem';
import InputLabel fr om '@mui/material/InputLabel';
import FormControl from '@mui/material/FormControl';
function LanguageSelector() {
const [language, setLanguage] = useState('');
const handleChange = (event) => {
setLanguage(event.target.value);
localStorage.setItem('selectedLanguage', event.target.value);
};
useEffect(() => {
const saved = localStorage.getItem('selectedLanguage');
if (saved) setLanguage(saved);
}, []);
return (
<FormControl fullWidth>
<InputLabel id="language-label">Язык</InputLabel>
<Sel ect
labelId="language-label"
value={language}
onCha nge={handleChange}
>
<MenuItem value="ru">Русский</MenuItem>
<MenuItem value="en">Английский</MenuItem>
<MenuItem value="fr">Французский</MenuItem>
</Select>
</FormControl>
);
}
Особенности:
value контролирует выбранный элемент.localStorage хранит строковое значение.value становится массивом, и
при сохранении требуется сериализация
(JSON.stringify/JSON.parse).Для больших приложений лучше использовать глобальное состояние для
управления выбором пользователя, чтобы изменения были доступны во всех
компонентах. Пример с Redux Toolkit:
// preferencesSlice.js
import { createSlice } fr om '@reduxjs/toolkit';
const initialState = {
darkMode: false,
};
export const preferencesSlice = createSlice({
name: 'preferences',
initialState,
reducers: {
setDarkMode: (state, action) => {
state.darkMode = action.payload;
localStorage.setItem('darkMode', action.payload);
},
loadPreferences: (state) => {
const saved = localStorage.getItem('darkMode') === 'true';
state.darkMode = saved;
},
},
});
export const { setDarkMode, loadPreferences } = preferencesSlice.actions;
export default preferencesSlice.reducer;
// DarkModeToggle.js
import React, { useEffect } from 'react';
import Switch from '@mui/material/Switch';
import { useSelector, useDispatch } from 'react-redux';
import { setDarkMode, loadPreferences } from './preferencesSlice';
function DarkModeToggle() {
const darkMode = useSelector((state) => state.preferences.darkMode);
const dispatch = useDispatch();
useEffect(() => {
dispatch(loadPreferences());
}, [dispatch]);
const handleChange = (event) => {
dispatch(setDarkMode(event.target.checked));
};
return <Switch checked={darkMode} onCha nge={handleChange} />;
}
Преимущества подхода:
localStorage для долговременного
хранения.MUI компоненты поддерживают defaultValue и
defaultChecked для инициализации состояния. В комбинации с
эффектами React можно загружать сохраненные настройки без
контролируемого состояния:
<Checkbox
defaultChecked={localStorage.getItem('newsletter') === 'true'}
onCha nge={(e) =>
localStorage.setItem('newsletter', e.target.checked)
}
/>
Этот способ удобен для простых форм, но для динамического интерфейса с зависимостями между элементами предпочтительно использовать контролируемые компоненты.
Если необходимо сохранять несколько настроек одновременно, удобно использовать объект состояния:
const [preferences, setPreferences] = useState({
notifications: true,
theme: 'light',
language: 'ru',
});
const handleChange = (key, value) => {
const updated = { ...preferences, [key]: value };
setPreferences(updated);
localStorage.setItem('preferences', JSON.stringify(updated));
};
useEffect(() => {
const saved = JSON.parse(localStorage.getItem('preferences'));
if (saved) setPreferences(saved);
}, []);
Особенности:
TextField,
Switch, Select.Для корпоративных приложений или SaaS рекомендуется сохранять настройки пользователя на сервере через API. Локальное хранилище используется для быстрой загрузки, а сервер гарантирует долговременное сохранение:
useEffect(() => {
fetch('/api/preferences')
.then(res => res.json())
.then(data => setPreferences(data));
}, []);
const savePreferences = () => {
fetch('/api/preferences', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(preferences),
});
};
MUI компоненты легко интегрируются с такой логикой, так как поддерживают контролируемые свойства и события изменения значений.