Задержка в useEffect, устанавливающая значение setState

У меня есть этот компонент, который отображает количество людей, которым понравилась книга, однако я не могу получить постоянный результат в своих состояниях.

Вот мой код:


///this is for getting the book details


  
const {id} = useParams();
const dispatch = useDispatch();
const[hasliked, sethasliked] = useState(null);

  useEffect(() => {
    const bookData = {
           id: id
        }
    dispatch(openBook(bookData))   
 }, [])

///and this is for setting the state of the component

const { bookFeatured, isLoading, isSuccess, openbook, likeStatus } = useSelector(state => state.book);
const { user, isError, message } = useSelector(state => state.auth);

  useEffect(()=>{


    if(openbook.noOfLikes?.find((noOfLikes) => noOfLikes === user._id)){

      sethasliked(true)

    }else{
      sethasliked(false)
    }


},[openbook])


  const Likes = () => {
   
      return hasliked
        ? (
          <><FaHeart fontSize="small"  />&nbsp;{hasliked.toString()}</>
        ) : (
          <><FaRegHeart  fontSize="small" fill='white'/>&nbsp;{hasliked.toString()}</>
        );
  };

дело в том, что я получаю противоречивый результат при получении значения от const hasliked, если мне уже понравилась книга, иногда она говорит мне, что hasliked ложно, но иногда оно становится истинным, из-за этого я каждый раз получал разные результаты. когда я визуализирую компонент, я думаю, что это как-то связано с задержкой использования эффекта из-за асинхронных действий. Могу ли я что-то с этим сделать?

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
1
0
57
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

  1. вы пытаетесь отобразить логическое значение с помощью .toString()? почему бы просто не сделать
   
      return hasliked
        ? (
          <><FaHeart fontSize="small"  />True</>


видя, как hasliked там уже верно.


  1. это
else{
      sethasliked(false)
    }

можно устранить, изменив инициализацию на

const[hasliked, sethasliked] = useState(false);


  1. если ваш dispatch(openBook(bookData)) возвращает обещание, вы можете установить hasliked в блоке .then, устраняя необходимость во втором эффекте использования

  1. изменить возврат от этого
return hasliked

к этому

return hasliked && openbook

для номера 1. я пытаюсь отладить, получаю ли я правильные значения из useState после установки его из useeffect, но кажется, что я получаю противоречивый результат на основе того, что рендерится из этой функции toString, 2. попытался изменить его, но проблема все еще сохраняется ( несоответствующее значение от понравилось) 4. попробовал также. но не решает проблему, я все еще думаю, могу ли я использовать 3, но из того, что я пробовал, я не могу установить состояние в блоке then()

JAS MAL 17.05.2022 06:46

Вы можете добавить loading state к своему компоненту и проверить, соответствует ли состояние загрузки true, а затем показать загрузчик или показать свой компонент.

const {id} = useParams();
const dispatch = useDispatch();
const[hasliked, sethasliked] = useState(null);
const [loading, setLoading] = useState(false) // The loading state

  useEffect(() => {
    setLoading(true) // Setting the loading state true
    const bookData = {
           id: id
        }
    dispatch(openBook(bookData))   
 }, [])

///and this is for setting the state of the component

const { bookFeatured, isLoading, isSuccess, openbook, likeStatus } = useSelector(state => state.book);
const { user, isError, message } = useSelector(state => state.auth);

  useEffect(()=>{    
    if(openbook.noOfLikes?.find((noOfLikes) => noOfLikes === user._id)){
      sethasliked(true)
      setLoading(false) // Setting loading state to false
    }else{
      sethasliked(false)
      setLoading(false) // Setting loading state to false
    }
},[openbook])


  const Likes = () => {
      // show a loader if loading is true
      if(loading) {
        return <div>Loading...</div>
      }   

      return hasliked
        ? (
          <><FaHeart fontSize="small"  />&nbsp;{hasliked.toString()}</>
        ) : (
          <><FaRegHeart  fontSize="small" fill='white'/>&nbsp;{hasliked.toString()}</>
        );
  };

попробовал это, я получаю те же значения (false) для состояния загрузки после возврата div, но значение hasliked по-прежнему несовместимо. Я думаю, что это как-то связано с функцией if(openbook.noOfLikes?.find((noOfLikes) => noOfLikes === user._id)) , она не находит noOflikes мгновенно, я думаю, что перед назначением правильные значения для hasliked , но до сих пор не знаю, как это исправить

JAS MAL 17.05.2022 07:48
Ответ принят как подходящий

Вы пробовали использовать setTimeout?

useEffect( () => {
  const tmr = setTimeout( () => { 
    const bookData = { id: id }
    dispatch( openBook(bookData) )
  }, 500)
  return () => clearTimeout(tmr);
 }, [])

useEffect( () => {
  const tmr = setTimeout( () => { 
    if (openbook.noOfLikes?.find( (noOfLikes) => noOfLikes === user._id) ) {
      sethasliked(true)
    } else { sethasliked( false) }
  }, 500)
  return () => clearTimeout(tmr);
},[openbook])

Здравствуйте, установка тайм-аута определенно помогает, я не понимаю, почему это происходит, но я не могу найти другого решения проблемы, поэтому я мог бы использовать это, спасибо!

JAS MAL 17.05.2022 08:15

@JASMAL setTimeout определенно будет работать здесь, но это не стандартное решение, потому что оно замедлит работу вашего приложения. Потому что независимо от того, сколько времени займет ваш запрос, он займет минимум 0,5 с, а это нехорошо.

Dharmik Patel 17.05.2022 08:22

@JASMAL У меня такая же проблема, как и у вас вчера, попробуйте использовать timeout и вуаля! проблема решена. Я предполагаю, что useEffect запускается сразу после рендеринга компонента, даже если вы еще не видели этот компонент. в любом случае добро пожаловать!

Musadarj 17.05.2022 08:23

@DharmikPatel, возможно, будет достаточно изменить интервал на 0,1 с, я лично установил интервал на 50, все еще работает (в моем приложении)

Musadarj 17.05.2022 08:27

@Musadarj это зависит от того, потому что каждый запрос занимает разное время, поэтому, если запрос не будет завершен за 0,1 с, у него снова будет та же проблема.

Dharmik Patel 17.05.2022 08:29

@DharmikPatel да, ты определенно прав

Musadarj 17.05.2022 08:31

Другие вопросы по теме