开发者问题收集

未捕获的类型错误:无法在我的 React 应用程序中读取未定义的属性(读取“长度”)

2022-05-18
1496

我正在开发一个 React 应用,但遇到了未捕获的类型错误。我按照在线教程操作,但无法修复。这是我的代码:

import React, { useState, useEffect, createRef } from 'react';
import { CircularProgress, Grid, Typography, InputLabel, MenuItem, FormControl, Select } from '@material-ui/core';

import PlaceDetails from '../PlaceDetails/PlaceDetails';
import useStyles from './styles.js';
const List = ({ places, type, setType, rating, setRating, childClicked, isLoading }) => {
  const [elRefs, setElRefs] = useState([]);
  const classes = useStyles();

  useEffect(() => {
    setElRefs((refs) => Array(places.length).fill().map((_, i) => refs[i] || createRef()));
  }, [places]);

  return (
    <div className={classes.container}>
      <Typography variant="h4">Food & Dining around you</Typography>
      {isLoading ? (
        <div className={classes.loading}>
          <CircularProgress size="5rem" />
        </div>
      ) : (
        <>
          <FormControl className={classes.formControl}>
            <InputLabel id="type">Type</InputLabel>
            <Select id="type" value={type} onChange={(e) => setType(e.target.value)}>
              <MenuItem value="restaurants">Restaurants</MenuItem>
              <MenuItem value="hotels">Hotels</MenuItem>
              <MenuItem value="attractions">Attractions</MenuItem>
            </Select>
          </FormControl>
          <FormControl className={classes.formControl}>
            <InputLabel id="rating">Rating</InputLabel>
            <Select id="rating" value={rating} onChange={(e) => setRating(e.target.value)}>
              <MenuItem value="">All</MenuItem>
              <MenuItem value="3">Above 3.0</MenuItem>
              <MenuItem value="4">Above 4.0</MenuItem>
              <MenuItem value="4.5">Above 4.5</MenuItem>
            </Select>
          </FormControl>
          <Grid container spacing={3} className={classes.list}>
            {places?.map((place, i) => (
              <Grid ref={elRefs[i]} key={i} item xs={12}>
                <PlaceDetails selected={Number(childClicked) === i} refProp={elRefs[i]} place={place} />
              </Grid>
            ))}
          </Grid>
        </>
      )}
    </div>
  );
};

export default List;

在使用在线教程中的 circularProgress 之前,我为我的位置创建了一个引用,他遇到了和我一样的错误,但当他使用 circularProgress 时,他能够修复它,但我不明白为什么我的错误无法修复

1个回答

看起来 places 属性是动态的,有时未定义。您可以提供一些后备值。在 places.length 访问上使用可选链接运算符,如果 places 为 null 或未定义,则提供 0 作为后备值。

useEffect(() => {
  setElRefs((refs) => Array(places?.length ?? 0)
    .fill()
    .map((_, i) => refs[i] || createRef())
  );
}, [places]);

您还可以提供默认的 places 属性值。

const List = ({
  places = [],
  type,
  setType,
  rating,
  setRating,
  childClicked,
  isLoading,
}) => {
  ...

更常见的模式是使用 React ref 来存储 refs 数组,而不是使用本地状态。示例:

const elRefs = React.useRef([]);

elRefs.current = Array(places?.length ?? 0)
  .fill()
  .map((_, i) => elRefs.current[i] || createRef());

...

{places?.map((place, i) => (
  <Grid ref={elRefs[i]} key={i} item xs={12}>
    <PlaceDetails
      selected={Number(childClicked) === i}
      refProp={elRefs.current[i]}
      place={place}
    />
  </Grid>
))}

这提供了更稳定的 ref 引用,因为在 places 属性更新时不会创建所有新的 refs。

Drew Reese
2022-05-18