Состояние изменилось, но метод рендеринга от реакции не срабатывает - PullRequest
0 голосов
/ 02 мая 2019

В настоящее время я сам обучаю себя коду и в данный момент погружаюсь в React.js.Я создаю простое приложение, которое отображает информацию о пиве, полученную через punkAPI (https://punkapi.com/documentation/v2).

). В моем приложении я хотел добавить некую «бесконечную» прокрутку, которая бы вытягивала больше данных из API, когда пользователь достигаетвнизу страницы.

В настоящее время метод handleScroll работает и обновляет состояние компонента, но не вызывает метод рендеринга, и мне было интересно, почему.

Я понимаю,что в моем коде много чего не так, и я планирую его реструктурировать, добавив некоторые логические значения в this.state, чтобы проверить, есть ли еще данные для загрузки, чтобы обрабатывать ошибки и не запускать метод handleScroll так интенсивно.

Однако мне все еще интересно, почему не происходит рендеринг, даже если состояние обновляется.

class BeerList extends Component {
    constructor() {
        super()
        this.state = {
            loading: false,
            beers: []
        }
        this.handleScroll = this.handleScroll.bind(this)
    }

    componentDidMount() {
        window.addEventListener('scroll', this.handleScroll, true);

        this.setState({
            loading: true
        })
        fetch("https://api.punkapi.com/v2/beers?per_page=12")
            .then(response => response.json())
            .then(data => {
                this.setState({
                    loading: false,
                    beers: data
                })
            })
    }

    handleScroll() {
        const checkForNewBeers = () => {
            let lastBeerCard = document.querySelector(".beer-list > div:last-child");
            let lastBeerCardOffset = lastBeerCard.offsetTop + lastBeerCard.clientHeight;
            let pageOffset = window.pageYOffset + window.innerHeight;

            if (pageOffset <= lastBeerCardOffset - 10) {
                return;
            }
            this.setState(prevState => {
                const beers = prevState.beers;
                const page = (prevState.beers.length / 12) + 1;
                fetch(`https://api.punkapi.com/v2/beers?per_page=12&page=${page}`)
                    .then(response => response.json())
                    .then(data => {
                        for (let item of data) {
                            beers.push(item);
                        }
                        console.log({
                            beers: beers
                        });
                        return {
                            beers: beers
                        }
                    });
            });
        }
        document.addEventListener("scroll", function (event) {
            checkForNewBeers();
        });
    }


    render() {
        let beerCards = []
        if (this.state.beers.length > 0) {
            beerCards = this.state.beers.map(beer => {
                return <BeerCard
                key = {
                    beer.id
                }
                img = {
                    beer.image_url
                }
                title = {
                    beer.name
                }
                description = {
                    beer.description
                }
                />
            })
        }

        return ( <
            div className = "container" >
            <
            div className = "row beer-list" > {
                beerCards
            } <
            /div> < /
            div >
        )
     }

}

export default BeerList


Таким образом, карты BeerCard правильно добавляются при загрузке страницы и при прокрутке консоли.Вы, что состояние обновляется (слишком много, но все же). Я ожидаю, что страница загружается дерьмо тонf BeerCards, но ничего не происходит.Почему это?

Ответы [ 3 ]

1 голос
/ 02 мая 2019

Вместо того, чтобы возвращать объект из вашей асинхронной fetch, вызовите setState внутри .then()

let beers = this.state.beers;
const page = (this.state.beers.length / 12) + 1;
fetch(`https://api.punkapi.com/v2/beers?per_page=12&page=${page}`)
    .then(response => response.json())
    .then(data => {
        for (let item of data) {
            beers.push(item);
        }

         this.setState({ beers });
    });
1 голос
/ 02 мая 2019

Как только вы вызовете fetch, который является последним оператором внутри setState, будет возвращено неопределенное значение.Попробуйте преобразовать параметр setState в асинхронную функцию:

this.setState(async prevState => {
  const beers = prevState.beers;
  const page = prevState.beers.length / 12 + 1;
  let response = await fetch(
    `https://api.punkapi.com/v2/beers?per_page=12&page=${page}`
  );
  response = await response.json();
  for (const item of response) {
    beers.push(item);
  }
  console.log({
    beers: beers
  });
  return {
    beers: beers
  };
});
0 голосов
/ 02 мая 2019

Ты так близко! Просто добавив ключевое слово «async» перед «prevState» в «this.setState» и «return await» перед «fetch», состояние вашего приложения должно быть обновлено и вызвать рендеринг, как и ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...