Почему бесконечная прокрутка в реакции не видит данных из функции map ()? - PullRequest
0 голосов
/ 07 сентября 2018

У меня проблема с этим кодом:

<InfiniteScroll
  dataLength={beers.length}
  next={fetchMoreBeers}
  hasMore={true}
  loader={<p>Loading ...</p>}
  endMessage={<p id="beers-end">No more beers :(</p>}
>
  {beers.map((beer, index) => (
    <div key={index}>
      <Link
        to={{
          pathname: `/beer/${beer.id}`,
          state: { beer: beer.id },
        }}
      >
        <div className="beer-wrapper">
          <div className="beer">
            <img
              className="beer-img"
              src={beer.image_url}
              alt={beer.name}
            />
            <p className="beer-name">
              {beer.name.length < 15
                ? `${beer.name}`
                : `${beer.name.substring(0, 20)}...`}
            </p>
            <p className="beer-tagline">
              {beer.tagline.length < 20
                ? `${beer.tagline}`
                : `${beer.tagline.substring(0, 25)}...`}
            </p>
          </div>
        </div>
      </Link>
      <Route path="/beer/:id" component={Beer} />
    </div>
  ))}
</InfiniteScroll>;

А при прокрутке страницы возникает ошибка:

"Ошибка типа: невозможно прочитать свойство 'id' из неопределенного"

для этой строки:

pathname: `/beer/${beer.id}`,

Похоже, что InfiniteScroll не видит данные из функции map () ....

Может быть, некоторые из вас знают, как решить эту проблему?

Спасибо за любые советы!

Ответы [ 4 ]

0 голосов
/ 07 сентября 2018

Я думаю, что эта проблема из-за ограничений записи данных в этом API.

0 голосов
/ 07 сентября 2018

Возможно, в массиве beers хранится значение undefined. Попробуйте отфильтровать их, вот так:

beers.filter(Boolean).map((beer, index) => ( 
  // ... 
)

Также я заметил, что hasMore prop всегда установлен на true. Чтобы посмотреть, поможет ли это, попробуйте что-то вроде:

<InfiniteScroll
  dataLength={beers.length}
  next={fetchMoreBeers}
  hasMore={beers.length < 25} // or hasMore={this.state.hasMore}
  loader={<p>Loading ...</p>}
  endMessage={<p id="beers-end">No more beers :(</p>}
> ...

EDIT:

Вы используете Array.from({ length: 20 })). Выходной массив будет содержать 20 undefined значений. Вот почему вы должны рассмотреть beers.filter(Boolean).

Полагаю, именно это вы и имели в виду:

this.setState({ 
  items: this.state.beers.concat(Array.from(this.state.beers))
})

или

this.setState({ 
  items: [...this.state.beers, ...this.state.beers]
})
0 голосов
/ 07 сентября 2018

Вы должны проверить код состояния при получении пива. fetch все равно позволит вам сделать свое дело, даже если запрос не выполнен. Если вы превысите лимит данных вашей конечной точки, вы добавите эти данные в ваш массив пива:

{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid query params",
  "data": [{
    "param": "per_page",
    "msg": "Must be a number greater than 0 and less than 80",
    "value": "100"
  }]
}

Как вы можете видеть, там нет параметра id, из-за которого появляется эта странная ошибка.

Включая валидатор схемы json (например, https://ajv.js.org/), чтобы убедиться, что данные в ожидаемом формате будут идеальным выбором.

0 голосов
/ 07 сентября 2018

Возможно, проблема в литералах шаблона. Когда мы добавляем шаблонные литералы напрямую, это вызывает такие проблемы. Я испытал то же самое в своих проектах.

Может быть, вы можете попробовать ниже

render(){
  const { beers } = this.props;
  const beerItems = beers.map((beer, index) => {
      let pathName = `/beer/${beer.id}`;
              return (
                <div key={index}>
                    <Link to={{ 
                        pathname: {pathName},
                        state: {"beer": beer.id}
                    }} >
                        <div className="beer-wrapper">       
                            <div className="beer">
                                <img className="beer-img" src={beer.image_url} alt={beer.name} />
                                <p className="beer-name">
                                    {beer.name.length < 15 ? beer.name : beer.name.substring(0, 20) }
                                </p>
                                <p className="beer-tagline">
                                    {beer.tagline.length < 20 ? beer.tagline : beer.tagline.substring(0, 25) }
                                </p>
                            </div>
                        </div>
                    </Link>
                    <Route path="/beer/:id" component={Beer} />
                </div>    
            )
            }

  return(
    <InfiniteScroll
            dataLength={beers.length}
            next={fetchMoreBeers}
            hasMore={true}
            loader={<p>Loading ...</p>}
            endMessage={<p id="beers-end">No more beers :(</p>}
        >    
            {beerItems}
        </InfiniteScroll>
  )
}
...