React не будет кэшировать результаты запроса API в локальном хранилище

#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>
    );
}