【问题标题】:Promise is not assignable to React statePromise 不可分配给 React 状态
【发布时间】:2021-09-26 08:08:45
【问题描述】:

来自MoviesPage.tsx,我正在调用movies.service.tsx 的函数来获取电影的数据(结果是一个包含对象的承诺,数据被正确获取,因为我可以控制它)。

但是,我无法将结果分配给状态,我收到一条消息“'Promise' 类型的参数不可分配给'SetStateAction' 类型的参数。”

我该如何解决? 谢谢!

MoviesPage.tsx

import React, {useState, useEffect} from "react";
import { fetchMovie } from "../../services/movies.service";
import {Grid, Card, CardMedia} from '@material-ui/core';
import noImage from '../../images/no-image-available.png';

interface Movie {
  id: number;
  title: string;
  vote_average: number;
  overview: string;
  poster_path?: string;
  date: string;
}

const MoviePage = (props: any) => {

  const [movie, setMovie] = useState<Movie>(
    {
      id: 0,
      title: '',
      vote_average: 0,
      overview: '',
      poster_path: noImage,
      date: '', 
    }
  );

const currentMovieId = window.location.pathname.split('/')[2];

useEffect(() => {

  const fetchedMovieInfo = fetchMovie(Number(currentMovieId));
  console.log(fetchedMovieInfo);
  // HERE I GET AN ERROR MESSAGE
  setMovie(fetchedMovieInfo);

}, [currentMovieId]);

  return (
    <>
      <Grid container spacing={3}>
        <Grid item xs={6} sm={3}>
          <Card className="card">
            <CardMedia
              component="img"
              alt={"Poster of " + movie.title}
              className="BeerListItem-img"
              image={posterBaseUrl + movie.poster_path}
              title={movie.title}
            />
          </Card>
        </Grid>
      </Grid>
    </>
  );
}

export default MoviePage;

movies.service.tsx

const movieApiBaseUrl = "https://api.themoviedb.org/3";


 export async function fetchMovie (currentMovieId: number ) {
  return await fetch(
    `${movieApiBaseUrl}/movie/${currentMovieId}?api_key=${process.env.REACT_APP_API_KEY}`
  )
    .then((res) => res.json())
    .then((body) => {
      console.log(body);
      return body;
  })
    .catch(() => {
        return {};
    });
}

【问题讨论】:

  • fetchMovie 是一个异步函数,它们总是返回承诺,所以 fetchedMovieInfo 确实是一个承诺。

标签: javascript reactjs typescript asynchronous promise


【解决方案1】:

您无需等待承诺解决,这可以通过@Viet 或then 回答的异步等待来完成,即

useEffect(() => {

  const fetchedMovieInfo = fetchMovie(Number(currentMovieId)).then((fetchedMovieInfo) => {
    console.log(fetchedMovieInfo); // this is now resolved
    setMovie(fetchedMovieInfo);
  }).catch(error => setErrorState(error)) // handle error case

}, [currentMovieId]);

使用useEffect 时遇到的一个问题是不能直接定义异步函数处理程序。这行不通……

useEffect(async () => { ...

您可以阅读原因,但基本上 useEffect 应该只返回一个函数来执行所需的任何清理。像这样定义一个内联异步函数会改为返回一个 promise,所以你会经常看到 .thenuseEffect 调用中使用

【讨论】:

  • 知道了,蒂姆,非常感谢您的回答!我将研究 promises 和 useEffect() 是如何工作的
【解决方案2】:

我们可以在useEffect中使用async/await来获取真实数据:

useEffect(() => {
  const callAPI = async () => {
    const fetchedMovieInfo = await fetchMovie(Number(currentMovieId));
    console.log(fetchedMovieInfo);
    setMovie(fetchedMovieInfo);
  }
  
  callAPI()
}, [currentMovieId]);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-11
    • 2016-09-18
    • 2018-03-20
    • 2020-12-07
    • 2018-04-23
    • 1970-01-01
    • 2021-09-25
    相关资源
    最近更新 更多