Вы фронтенд-разработчик в команде, которая внедряет - Ответ на вопрос по РВПЯJS №2495996
Новинка
Вопрос
Вы фронтенд-разработчик в команде, которая внедряет страницу профиля в SPA на React + TypeScript. Требования заказчика (см. ниже):• страница доступна по маршруту /users/:id (React Router v6);
• данные профиля подтягиваются с GET /api/users/:id;
• при смене :id происходит повторная загрузка;
• предыдущий запрос корректно отменяется при размонтировании/смене :id;
• для авторизации в заголовок уходит токен из localStorage;
• без глобального состояния, только локальный useState;
• корректная типизация ответа;
• отображать «Загрузка…» во время запроса и имя пользователя после.
Какой из фрагментов компонента реализует требования наилучшим образом?
- function Profile() { const { id } = useParams(); const [user, setUser] = useState˂any˃(null); useEffect(() =˃ { fetch(`/api/users/${id}`, { headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } }) .then(r =˃ r.json()) .then(setUser); }, []); // ← не реагирует на смену id, нет отмены запроса if (!user) return ˂p˃Загрузка…˂/p˃; return ˂h1˃{user.name}˂/h1˃; }
- type Profile = { id: number; name: string; email: string }; export default function ProfilePage() { const { id } = useParams(); const [data, setData] = useState˂Profile | null˃(null); const [loading, setLoading] = useState(false); const [error, setError] = useState˂string | null˃(null); useEffect(() =˃ { const ctrl = new AbortController(); const token = localStorage.getItem('token'); setLoading(true); setError(null); setData(null); fetch(`/api/users/${id}`, { method: 'GET', signal: ctrl.signal, headers: { Authorization: `Bearer ${token ?? ''}` } }) .then(r =˃ { if (!r.ok) throw new Error(`HTTP ${r.status}`); return r.json() as Promise˂Profile˃; }) .then(setData) .catch(e =˃ { if (e.name !== 'AbortError') setError(e.message); }) .finally(() =˃ setLoading(false)); return () =˃ ctrl.abort(); }, [id]); if (loading) return ˂p˃Загрузка…˂/p˃; if (error) return ˂p˃Ошибка: {error}˂/p˃; if (!data) return null; return ˂h1˃{data.name}˂/h1˃; }
- function Profile() { const { id } = useParams(); const [user, setUser] = useState˂{ name: string } | null˃(null); useLayoutEffect(() =˃ { // Нет обработки токена, нет отмены, возможны гонки fetch('/api/users/' + id) .then(r =˃ r.json()) .then(setUser); }, [/* пусто */]); // ← зависимостей нет return user ? ˂h1˃{user.name}˂/h1˃ : ˂span/˃; }
- // Использует Redux store для хранения профиля — нарушает требование «без глобального состояния» function Profile() { const { id } = useParams(); const dispatch = useAppDispatch(); const user = useAppSelector(s =˃ s.user.byId[id!]); useEffect(() =˃ { dispatch(fetchUser(id!)); }, [id]); return user ? ˂h1˃{user.name}˂/h1˃ : ˂p˃Загрузка…˂/p˃; }
Ответ
Этот вопрос в коллекциях
-25%

Я был поражен тем, как важно предпринимать действия. Недостаточно просто знать, нужно использовать знания. Мало хотеть чего-то, нужно делать. - Леонардо Да Винчи





















