如何解决 firebase 数据库的延迟问题?

时间:2021-05-16 19:23:02

标签: reactjs firebase

这是我的函数代码:

function Detail() {
  const { id } = useParams();
  const [movie, setMovie] = useState();
  useEffect(() => {
    // Grab the movie info from db
    db.collection("movies")
      .doc(id)
      .get()
      .then((doc) => {
        if (doc.exists) {
          // save the movie to the state
          setMovie(doc.data());
        } else {
          // redirect to home page
          console.log("no such document in firebase ?");
        }
      });
  }, [id]);

  return (
    <Container>
      <Background>
        <img alt=" background" src={movie.backgroundImg} />
      </Background>
      <ImageTitle>
        <img alt="title" src={movie.titleImg} />
      </ImageTitle>

      <SubTitle>{movie.subtitle}</SubTitle>
      <Description>{movie.description}</Description>
    </Container>
  );
}

这里一切正常,但是当我运行应用程序时,出现 TypeError: cannot read property 'backgroundImg' of undefined

经过几个小时的调试和研究,我发现问题在于,函数在没有时间从数据库中获取数据之前就开始寻找数据。

这里的解决方案是什么?我知道异步函数,但以前从未使用过。

4 个答案:

答案 0 :(得分:0)

UseEffect 在渲染后和值 id 值改变时执行

注意=>仅当电影存在时才需要渲染

function Detail() {
  const { id } = useParams();
  const [movie, setMovie] = useState();
  useEffect(() => {
    // Grab the movie info from db
    const unsubscribe=db.collection("movies")
      .doc(id)
      .get()
      .then((doc) => {
        if (doc.exists) {
          // save the movie to the state
          setMovie(doc.data());
        } else {
          // redirect to home page
          console.log("no such document in firebase ?");
        }
      });
      return ()=>{
      //clean up function to unsubscribe to firestore changes
      unsubscribe();
    }
  }, [id]);

  return (
    <Container>
    //render only if movie exists
    {
    movie ? <div>
        <Background>
            <img alt=" background" src={movie.backgroundImg} />
          </Background>
          <ImageTitle>
            <img alt="title" src={movie.titleImg} />
          </ImageTitle>

          <SubTitle>{movie.subtitle}</SubTitle>
          <Description>{movie.description}</Description>
          </div>
      : <p>...loading</p>
    }
    </Container>
  );
}

答案 1 :(得分:0)

您可以在 react 中使用条件渲染并基于 movie 渲染不同的组件

return (
    <Container>
{movie?
<React.Fragment>
      <Background>
        <img alt=" background" src={movie.backgroundImg} />
      </Background>
      <ImageTitle>
        <img alt="title" src={movie.titleImg} />
      </ImageTitle>

      <SubTitle>{movie.subtitle}</SubTitle>
      <Description>{movie.description}</Description>
</React.Fragment>
: <p>loading from firebase</p>}
    </Container>
  );

答案 2 :(得分:0)

您可能需要一些加载状态来控制内容是否可用,这是重构后的代码:

ps:如果它不起作用,请检查您的日志,以便我们查看错误

function Detail() {
  const { id } = useParams();
  const [loading, setLoading] = useState(false)
  const [movie, setMovie] = useState();

  useEffect(() => {
    setLoading(true)
    async function getMovie(id) {
      try {
        const doc = await db.collection("movies")
          .doc(id)
          .get()

        if (doc.exists()) {
          setMovie(doc)
        }
      }
      catch (err) {
        console.log(err)
      }
    }

    getMovie(id)

    setLoading(false)
  }, []);

  return (
    <Container>
      {!loading && (
        <>
          <Background>
            <img alt=" background" src={movie.backgroundImg} />
          </Background>
          <ImageTitle>
            <img alt="title" src={movie.titleImg} />
          </ImageTitle>

          <SubTitle>{movie.subtitle}</SubTitle>
          <Description>{movie.description}</Description>
        </>
      )}
    </Container>
  );
}

答案 3 :(得分:0)

在 React 中,永远不要假设请求将被处理并且信息将存在或 React 将在请求完成处理之前呈现。所以你总是想使用 && 运算符

function Detail() {
  const { id } = useParams();
  const [movie, setMovie] = useState();
  useEffect(() => {
    // Grab the movie info from db
    db.collection("movies")
      .doc(id)
      .get()
      .then((doc) => {
        if (doc.exists) {
          // save the movie to the state
          setMovie(doc.data());
        } else {
          // redirect to home page
          console.log("no such document in firebase ?");
        }
      });
  }, [id]);

  return (
    {movie &&
    <Container>
      <Background>
        <img alt=" background" src={movie.backgroundImg} />
      </Background>
      <ImageTitle>
        <img alt="title" src={movie.titleImg} />
      </ImageTitle>

      <SubTitle>{movie.subtitle}</SubTitle>
      <Description>{movie.description}</Description>
    </Container>}
  );
}
相关问题