TypeError: Cannot read properties of undefined (reading 'map'), and multiple API requests in React.js

TypeError: Cannot read properties of undefined (reading 'map'), and multiple API requests in React.js

我知道这个地图读取错误已经被问过 很多 并且我查看了几个已关闭的问题,但由于它们的原因与我的不同我选择打开一个新话题。目前我面临 2 个错误,所以让我一次解决一个。

我想完成的事情: 提交搜索查询后,应呈现“结果”组件并向我的后端发出 GET 请求(反过来,将向外部发出 GET 请求 API 并将结果发送回 React)。获取数据后,它应将其存储在 details 变量中,该变量将在子组件中映射和呈现。

第一个问题:

尽管向我的后端和外部 API 发出了一个成功的请求——我可以使用 console.log 来检查——但似乎检索到的数据不是被存储在变量中,导致映射一个未定义的数组。那么,我在这里做错了什么?发生这种情况是因为组件试图在 GET 请求完成并执行 setDetails(response.data) 之前映射数组,即使它出现在代码下方?

function Results() {
  const location = useLocation();
  const history = useHistory();
  const [query, setQuery] = useState(location.state.search);
  const [details, setDetails] = useState([]);

  axios.get("http://localhost:5000/results/" + query).then((response) => {
    setDetails(response.data);
    console.log(response.data);
  });

  const results = details.total_results;
  const pages = details.total_pages;
  const baseURL = "https://image.tmdb.org/t/p/w154";

  return (
    <Container>
      <Card sx={{ padding: 3, margin: 2 }}>
        <CardContent>
          <Grid container>
            <Grid item xs={12}>
              <Typography variant="h5">Results</Typography>
              <Typography>{results ? results : 0} results found</Typography>
            </Grid>
            <Grid item xs={12}>
              <List sx={{ mt: 5 }}>
                {details.results.map((result) => {
                  return (
                    <ResultItem
                      key={result.id}
                      imgURL={baseURL + result.poster_path}
                      title={result.title}
                      year={result.release_date}
                      director=""
                      synopsis={result.overview}
                    />
                  );
                })}
              </List>
            </Grid>
          </Grid>
        </CardContent>
        <Pagination
          count={pages}
          onChange={(event, page) => {
            history.push("/results" + query + "&page=" + page);
            setQuery(query + "&page=" + page);
          }}
        />
      </Card>
    </Container>
  );
}

export default Results;

第二题:

我不确定具体原因,但是 GET 请求触发了来自外部 API 的 两个 响应,而不是一个。前端和后端都两次记录检索到的数据,我怀疑多个请求来自我的前端,导致后端也触发多个请求。当我的代码中的某些内容触发请求的无限循环时,这与之前的错误相比迈出了一大步。

我想我以后可能也会遇到分页问题,​​但那是另一回事了。

第一期

初始details状态是一个数组,而不是具有results数组的对象属性。

const [details, setDetails] = useState([]);

因此尝试映射 details.results 会导致错误“无法读取未定义的 属性 X。

要解决此问题,请使用与以后使用方式相匹配的有效初始 details 状态。它应该是一个具有有效 results 数组 属性.

的对象
const [details, setDetails] = useState({ results: [] });

第二期

您正在调用函数组件主体中的 axios 请求,这是一个无意的副作用。这可能是将您的应用渲染到 React.StrictMode 组件中的结果,该组件会双重调用某些生命周期方法和函数作为 detect unexpected side-effects 的一种方式,函数体就是其中之一。

您应该将其移动到 useEffect 挂钩中,并将 query 作为依赖项。

useEffect(() => {
  axios.get("http://localhost:5000/results/" + query)
    .then((response) => {
      setDetails(response.data);
    });
}, [query]);