Инициализация значения состояния с помощью функции - PullRequest
0 голосов
/ 09 июля 2020

Итак, по существу, для каждого компонента «пост» я хочу go в базу данных и проверять, понравился ли мой пользователь пост или нет. Для этого я делаю следующее. Обратите внимание, что нравится - это состояние, которое проверяет, нажата ли кнопка Like или нет.

const getLike = ()=>{
        if(!props.item.item){
            const a = db().collection("posts").doc(props.item.id).collection("likes").doc(props.myInfo.uid).get()
            .then((data)=>{
                if(data){
                       return true
                }
             })
            }
    return false
}


const [liked, setLiked] = useState(getLike())

Проблема в том, что по какой-то причине она всегда возвращает false. Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 09 июля 2020

Проблема здесь в том, что вы используете Promise, т. Е. db().collection("posts").... асинхронно, поэтому .then будет вызываться только при получении ответа от сервера. Но он не остановит выполнение следующих строк кода, например, return false. Таким образом, после выполнения вызова db().collection("posts").... следующая строка также будет выполнена. Вот почему false возвращается всегда.

Ниже приведены примеры моделирования Promises

const promiseFn = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Resolved")
    }, 1000)
  })
}

const promiseFnCall1 = () => {
  promiseFn().
  then(res => console.log(res))
  
  //This will be executed before `promiseFn` returns the response
  console.log("This is executed first");
}

promiseFnCall1();


//If there's some operation that needs to be performed only
//after the success response from a Promise that should be
//done in .then method
const promiseFnCall2 = () => {
  promiseFn().
  then(res => {
    console.log(res);
    console.log("This is the correct order of execution");
  }) 
}

promiseFnCall2();

Также не рекомендуется вызывать обещание для инициализации состояния с помощью useState, вместо этого вы можете инициализировать состояние значением по умолчанию как false и использовать useEffect , чтобы получить данные из бэкэнда и обновить их соответствующим образом.

const [liked, setLiked] = useState(false);

useEffect(() => {
  if (!props.item.item) {
    const a = db().collection("posts").doc(props.item.id).collection("likes").doc(props.myInfo.uid).get()
      .then((data) => {
        if (data) {
          setLiked(true)
        }
      })
  }
}, [])

Надеюсь, это поможет.

0 голосов
/ 09 июля 2020

Это потому, что часть if в getLike вызывает Promise и возвращает истину в цепочке then.

Вы должны изменить свой код следующим образом:

const [liked, setLiked] = useState(false);

const getLike = ()=>{
        if(!props.item.item){
            const a = db().collection("posts").doc(props.item.id).collection("likes").doc(props.myInfo.uid).get()
            .then((data)=>{
                if(data){
                       setLiked(true) // we call our setLiked after the promise has resolved.
                }
             })
            }
}

useEffect(() => getLike(), []) // we want to call getLike() only once after the component has mounted.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...