Все хуки должны вызываться до условного return и вне if. Условия перенесите внутрь эффекта, добавьте зависимости gameId/platform, обработку ошибки и защиту от устаревшего ответа.
Оптимизация и улучшение React‑компонента
Все хуки должны вызываться до условного return и вне if. Условия перенесите внутрь эффекта, добавьте зависимости gameId/platform, обработку ошибки и защиту от устаревшего ответа.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Дан React‑компонент Game. Требуется провести рефакторинг, исправив неправильное использование хуков и улучшив читаемость кода.
export const Game = ({ gameId }) => {
const currentPlatform = useSelector(selectSiteVersion); // 'mobile' | 'desktop'
const [loading, setLoading] = useState(false);
const [fullScreen, setFullScreen] = useState(false);
const [gameInfo, setGameInfo] = useState({ title: '', description: '' });
if (!gameId) {
return <div>Empty</div>;
}
const requestParams = {
id: gameId,
mode: 'real',
platform: currentPlatform,
};
const fetchGame = async () => {
setLoading(true);
const game = await requestGame(requestParams);
setLoading(false);
setGameInfo(game);
};
if (currentPlatform === 'mobile') {
useEffect(() => {
fetchGame();
}, []);
}
useEffect(() => {
const handler = () => setFullScreen(prev => !prev);
document.addEventListener('fullscreenchange', handler);
return () => document.removeEventListener('fullscreenchange', handler);
}, []);
return (
<div>
<div>{gameInfo.title}</div>
<div>{gameInfo.description}</div>
{loading && <div>Loading...</div>}
</div>
);
};
Ответ
Все хуки должны вызываться до условного return и вне if. Условия перенесите внутрь эффекта, добавьте зависимости gameId/platform, обработку ошибки и защиту от устаревшего ответа.
После useState добавьте error и замените эффекты; ранний return перенесите ниже них.
const [error, setError] = useState('');
useEffect(() => {
let active = true;
setGameInfo({ title: '', description: '' });
setError('');
if (!gameId || currentPlatform !== 'mobile') {
setLoading(false);
return;
}
setLoading(true);
(async () => {
try {
const game = await requestGame({ id: gameId, mode: 'real', platform: currentPlatform });
if (active) setGameInfo(game);
} catch {
if (active) setError('Не удалось загрузить игру');
} finally {
if (active) setLoading(false);
}
})();
return () => { active = false; };
}, [gameId, currentPlatform]);
useEffect(() => {
const handler = () => setFullScreen(Boolean(document.fullscreenElement));
handler();
document.addEventListener('fullscreenchange', handler);
return () => document.removeEventListener('fullscreenchange', handler);
}, []);
Покажите error в JSX и используйте fullScreen для интерфейса либо удалите ненужное состояние. Здесь сохранено исходное правило загрузки только на mobile; если игра нужна и на desktop, уберите это условие явно. Отмена сетевого запроса требует поддержки signal в requestGame; active лишь предотвращает позднюю запись состояния.