TypeError:无法读取未定义的属性(读取“地图”),以及 React.js 中的多个 API 请求

Posted

技术标签:

【中文标题】TypeError:无法读取未定义的属性(读取“地图”),以及 React.js 中的多个 API 请求【英文标题】:TypeError: Cannot read properties of undefined (reading 'map'), and multiple API requests in React.js 【发布时间】:2021-12-26 07:32:37 【问题描述】:

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

我想要完成的事情: 提交搜索查询后,应该呈现“结果”组件并向我的后端发出 GET 请求(反过来,它将向外部 API 发出 GET 请求并将结果发送回 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 的两个响应,而不仅仅是一个。前端和后端都两次记录检索到的数据,我怀疑多个请求来自我的前端,导致后端也触发多个请求。当我的代码中的某些内容触发无限循环的请求时,这与之前的错误相比是一个巨大的进步。

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

【问题讨论】:

【参考方案1】:

问题一

初始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]);

【讨论】:

以上是关于TypeError:无法读取未定义的属性(读取“地图”),以及 React.js 中的多个 API 请求的主要内容,如果未能解决你的问题,请参考以下文章

未处理的拒绝(TypeError):无法读取反应中未定义的属性“setState”(firestore)

如何使用自定义错误消息捕获“TypeError:无法读取未定义的属性(读取'0')”?

TypeError:无法读取未定义的属性(读取“名称”)

TypeError:无法在 gitlab 中读取未定义的属性(读取“读取”)

TypeError:无法读取未定义的属性(读取“问题”)

TypeError:无法读取未定义的属性(读取“匹配”):