#reactjs #web-component
#reactjs #веб-компонент
Вопрос:
Я пытаюсь создать очень простой component
in react
, который запрашивает изображение из API и впоследствии сохраняет / кэширует его для любого другого запроса в приложении, когда используется этот компонент.
На данный момент компонент ВСЕГДА отображается, и как таковой — если у меня есть компонент несколько раз на странице (т. Е. В первых 10 результатах) Я получаю несколько вызовов API, тогда как я ожидал получить только 1 вызов API, результат возвращается и застревает в localstorage
.
У кого-нибудь есть идеи? Должен ли я использовать useMemo
или что-то еще? Есть идеи о том, как предотвратить множественные вызовы API?
import React, {useState, useEffect} from 'react';
import UserService from '../../api/UserService';
const ProfileImage = () => {
const userService = new UserService();
const [avatar, setAvatar] = useState();
const cachedAvatar = localStorage.getItem('avatar');
const mount = () => {
console.log(cachedAvatar);
if (cachedAvatar) {
setAvatar(cachedAvatar);
} else {
userService.getUser().then((res)=>{
setAvatar( res.avatarUrl );
localStorage.setItem('avatar', res.avatarUrl);
});
}
}
/* unmount cleanup */
useEffect(() => {
mount();
},[]);
return (
<img src={ avatar ? avatar : require('../../img/placeholder/avatar.png')}></img>
);
};
export default ProfileImage;
Комментарии:
1.поместите
localStorage.setItem('avatar', res.avatarUrl);
передsetAvatar( res.avatarUrl );
, чтобы убедиться, что он кэширован перед рендерингом2. @NikosM. тот же результат 10 вызовов API, затем запускается кэш.
3. да, я понимаю, почему. Это потому, что в первый раз для извлечения ресурса требуется некоторое время, но за это время вы уже отобразили некоторые изображения. Таким образом, решением было бы добавить перехват жизненного цикла в
componentDidMount
, чтобы затем извлекать и кэшировать запрос и повторно отображать. Изначально вы должны выполнить рендеринг с некоторой загрузкой.. для текста и состояния.loading установлено значение true. Если вы предоставите больше информации, я могу даже опубликовать ответ в следующих строках
Ответ №1:
У вас есть несколько вызовов API, потому что аватар выполняется внутри localStorage только после завершения первого вызова. Использование localStorage не является правильным решением.
Вам не нужно каждый раз вызывать getUser. Например:
const userService = new UserService();
let getUserCall;
// create a custom hook
const useAvatar = () => {
const [avatar, setAvatar] = useState();
useEffect(() => {
if (!getUserCall) {
getUserCall = userService.getUser();
}
getUserCall.then(res => setAvatar(res.setAvatar))
},[]);
return avatar;
}
Затем внутри вашего компонента используйте useAvatar
хуки.
const ProfileImage = () => {
const avatar = useAvatar();
return (
<img src={ avatar ? avatar : defaultAvatar }>
</img>
);
}