Хотя иногда это работает, я получаю «.filter не является функцией» в моем проекте React

#javascript #reactjs #filter

Вопрос:

   28 | <Grid.Row>
  29 |   {cars.map((car) => (
  30 |     <Grid.Column style={{marginBottom:"1em"}}>
> 31 |       <CarComponent car={car} imagePath={carImages.filter(image=>image.car.id===car.id)[0].imagePath}></CarComponent>
     | ^  32 |       
  33 |     </Grid.Column>
  34 |   ))}
 

Я получаю информацию (марка, цвет, описание и т.д.) и фотографии транспортных средств из отдельных служб (CarController, carImageController). Таким образом, при попытке перечислить автомобили я выбираю фотографию с идентификатором автомобиля, равным идентификатору этого автомобиля, в списке фотографий для каждого автомобиля в списке автомобилей. Я пишу путь к изображению в виде карикатур.фильтр(изображение=>image.car.id===car.id)[0].Путь к изображению} для этого проверьте данные, поступающие из моего фотосервиса, и отправьте их в качестве реквизита в компонент автомобиля. Иногда я получаю эту ошибку типа, когда все работает нормально. Почему это может быть вызвано?

Функциональный Компонент Автомобиля:

  export default function CarComponent({ car, imagePath}) {
return (
<div>
  <Card style={{height:"388px"}}>
    <Image 
      src={imagePath}
      wrapped
      ui="false"
      style={{height:"200px"}}
      
    />
    <Card.Content>
      <Card.Header>{car.brand.name}</Card.Header>
      <Card.Meta>
        <span className="date">{car.modelYear}</span>
      </Card.Meta>
      <Card.Description>{car.description}</Card.Description>
    </Card.Content>
    <Card.Content extra style={{color:"black"}} >
      <h3 >{car.dailyPrice} ₺</h3>

      <Button secondary animated>
        <Button.Content visible>Kirala</Button.Content>
        <Button.Content hidden>
          <Icon name="arrow right" />
        </Button.Content>
      </Button>
    </Card.Content>
  </Card>
</div>
);}
 

Класс Изображения Автомобиля

 export default class CarImageService{
getCarImages(){
    return axios.get("http://localhost:8080/api/images/getAll")
}
}
 

Страница списка автомобилей

 export default function CarsList() {


const [cars, setCars] = useState([]);

  const [carImages, setCarImage] = useState({});

  useEffect(() => {
    let carImageService = new CarImageService();
    carImageService
      .getCarImages()
      .then((result) => setCarImage(result.data.data));
      
  }, []);

  useEffect(() => {
    let carService = new CarService();
    carService.getCars().then((result) => setCars(result.data.data));
  }, []);

  return (
    <div>
      <Grid columns={3} >
        <Grid.Row>
          {cars.map((car) => (
            <Grid.Column style={{marginBottom:"1em"}}>
              <CarComponent car={car} imagePath={carImages.filter(image=>image.car.id===car.id)[0].imagePath}></CarComponent>
              
            </Grid.Column>
          ))}
        </Grid.Row>
       
      </Grid>
    </div>
  );
}
 

Получить все изображения автомобилей по URL-адресу запроса: http://localhost:8080/api/images/getAll

Получите Все Изображения Автомобиля В Теле:

 {
  "success": true,
  "message": null,
  "data": [
    {
      "id": 26,
      "imagePath": "http://res.cloudinary.com/dp39jsge0/image/upload/v1629406293/hx80jyfrus88tar0psq4.png",
      "createdAt": "2021-08-19",
      "car": {
        "id": 1,
        "modelYear": 2017,
        "dailyPrice": 600,
        "description": "A6 2.0TDI QUATTRO EDITION",
        "brand": {
          "id": 2,
          "name": "Audi"
        },
        "color": {
          "id": 8,
          "name": "Beyaz"
        },
        "busy": false
      }
    },
    {
      "id": 27,
      "imagePath": "http://res.cloudinary.com/dp39jsge0/image/upload/v1629406541/dynoc7dnjcbns0mv2y1m.png",
      "createdAt": "2021-08-19",
      "car": {
        "id": 2,
        "modelYear": 2018,
        "dailyPrice": 400,
        "description": "ALFA ROMEO GIULIETTA 1.6 JTD PROGRESSİON 120 HP",
        "brand": {
          "id": 1,
          "name": "Alfa Romeo"
        },
        "color": {
          "id": 9,
          "name": "Gri"
        },
        "busy": false
      }
    },
    {
      "id": 28,
      "imagePath": "http://res.cloudinary.com/dp39jsge0/image/upload/v1629406744/fmvdbmqaennil4ptdyoc.png",
      "createdAt": "2021-08-19",
      "car": {
        "id": 3,
        "modelYear": 2018,
        "dailyPrice": 550,
        "description": "BMW 320 DİZEL OTOMATİK-EDITION M SPORT",
        "brand": {
          "id": 3,
          "name": "BMW"
        },
        "color": {
          "id": 10,
          "name": "Kırmızı"
        },
        "busy": false
      }
    },
    {
      "id": 29,
      "imagePath": "http://res.cloudinary.com/dp39jsge0/image/upload/v1629406930/dq4htj3rrdjlbpiqa8iq.png",
      "createdAt": "2021-08-20",
      "car": {
        "id": 4,
        "modelYear": 2016,
        "dailyPrice": 700,
        "description": "C180 COUPE",
        "brand": {
          "id": 10,
          "name": "Mercedes - Benz"
        },
        "color": {
          "id": 11,
          "name": "Lacivert"
        },
        "busy": false
      }
    }
  ]
}
 

Обновите страницу несколько раз:пример списка автомобилей

Комментарии:

1. Потому что у некоторых автомобилей нет фотографий, поэтому carImages есть null , и вы не можете фильтровать по нулю?

2. Изменить const [carImages, setCarImage] = useState({}); на const [carImages, setCarImage] = useState([]);

3. Спасибо вам всем. На данный момент это работает нормально. Я забыл вернуть начальное состояние из объекта в массив.

4. Ребята, я думаю, на этот раз есть проблема с ImagePath. «Не удается прочитать свойство» Путь к изображению «неопределенного» возникает ошибка. Я использую . правильно ли метод filter ()? Я попытался создать CarComponent с помощью: фильтр(изображение=>image.car.id===car.id)[0].Путь к изображению}>>>></CarComponent>. там есть [0], потому что только таким образом я достигаю строки чистого пути. Нулевой индекс карикатур. фильтр(изображение=>image.car.id===car.id) является фактическим объектом карикатуры. (@Dominik вы можете перенести этот ответ на этот вопрос, если это необходимо)

Ответ №1:

Начальное значение для carImages должно быть массивом, а не объектом.

const [carImages, setCarImage] = useState([]);

Обратите внимание на начальное значение: [] , не {}

За вторую ошибку:

Вам нужно проверить результат filter , потому filter что возвращает пустой массив, когда getCars() возвращается раньше getCarImages() , или если у некоторых автомобилей нет изображений. Кроме того, чтобы избавиться от массива, вам нужно использовать find вместо filter , потому что вы ожидаете одного результата.

 export default function CarsList() {


const [cars, setCars] = useState([]);

  const [carImages, setCarImage] = useState([]);

  useEffect(() => {
    let carImageService = new CarImageService();
    carImageService
      .getCarImages()
      .then((result) => setCarImage(result.data.data));
      
  }, []);

  useEffect(() => {
    let carService = new CarService();
    carService.getCars().then((result) => setCars(result.data.data));
  }, []);

  return (
    <div>
      <Grid columns={3} >
        <Grid.Row>
          {cars.map((car) => {
            let image = carImages.find(i=>i.car.id===car.id);
            return 
            <Grid.Column style={{marginBottom:"1em"}}>
              <CarComponent car={car} imagePath={image === undefined ? undefined :image.imagePath}></CarComponent>
              
            </Grid.Column>
          })}
        </Grid.Row>
       
      </Grid>
    </div>
  );
}