Как я могу получить componentDidUpdate (), чтобы прекратить делать запросы на выборку? - PullRequest
0 голосов
/ 13 марта 2020

У меня есть сетка, которая при нажатии на плитку отображает выпадающий список. Я извлекаю содержимое из локального файла JSON, который я создал. Плитка создается для каждого объекта в файле JSON.

в файле JSON, у меня есть свойство isActive - по умолчанию оно false, затем при нажатии оно меняется на true.

[
    {
        "title": "title one",
        "body": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Quam, voluptate",
        "isActive": false,
        "image": {
            "src": "/images/Cinco-de-Mayo_2-600x436.jpg",
            "alt": "some text"
        },
        "cta": {
            "text": "Learn more",
            "link": "https://reactjs.org/",
            "open": true
        }
    }
]

ПРОВАЙДЕР КОНТЕКСТА:


import React, { Component, createContext } from 'react';

export const TileContext = createContext();

export class TileProvider extends Component {
    state = {
        tileShowCount: 4,
        loading: true,
        tiles: [],
        handleDropDown: (id) => {

        this.setState(prevState => ({
                tiles: prevState.tiles.map((tile, i) => ({
                    ...tile,
                    isActive: ( id === i ) ? !this.state.tiles[id].isActive : false
                }))
            }));

        },

        handleDropDownKeyPress: (id, e) => {

            if(e.key === 'Enter'){

                this.setState(prevState => ({
                    tiles: prevState.tiles.map((tile, i) => ({
                      ...tile,
                      isActive: ( id === i ) ? !this.state.tiles[id].isActive : false
                    }))
                  }));

            }

        },

        fetchData: async (url) => {
            let res = await fetch(url)
            let data = await res.json();

            return data
        },

        loadMore: () => {

                this.setState( prevState => {
                    return {
                        tileShowCount: prevState.tileShowCount += 4
                    }

                })
        }
     }

     componentDidMount() {
        this.state.fetchData('/data/tileInfo.json')
        .then((res) => {
            this.setState( prevState => {
                    return {
                        tiles: res.slice(0, this.state.tileShowCount), 
                        loading: false
                    }
                });
            })
        .catch((err) => {console.log(err);})
     }

     componentDidUpdate(prevProps, prevState) {

        console.log('prevstate:', prevState.tileShowCount, 'currentstate:', this.state.tileShowCount);

        if(prevState.tiles !== this.state.tiles) {

            this.state.fetchData('/data/tileInfo.json')
            .then((res) => {
                this.setState( prevState => {
                        return {
                            tiles: res.slice(0, this.state.tileShowCount), 
                            loading: false
                        }
                    });
                })
            .catch((err) => {console.log(err);})

        } 

     }


    render() { 
        return ( 
            <TileContext.Provider value={{...this.state}}>
                {this.props.children}
            </TileContext.Provider>
         );
    }
}



У меня есть две проблемы с этим:

1: componentDidUpdate() продолжает отправлять запрос на JSON файл. Я проверил вкладку сети в chrome Dev tools и увидел, что она зацикливается.

2: Каждый раз, когда я нажимаю на плитку, она открывается, а затем немедленно снова закрывает плитку, потому что запрос на выборку Файл JSON сбрасывает свойство isActive обратно в исходное состояние: false

По сути, я пытаюсь загружать больше плиток, когда вы нажимаете кнопку «Загрузить еще». Итак, я использую метод slice для извлечения начальных 4 плиток из массива JSON. Затем при нажатии «загрузить еще» будет обновлен метод slice, чтобы извлечь еще 8 фрагментов из файла JSON.

ЗАГРУЗИТЬ БОЛЬШЕ КОМПОНЕНТА:

Функция loadMore увеличивает число на 8 при нажатии. Затем обновляется tileShowCount в поставщике контекста. Затем tileShowCount используется в методе slice для обновления свойства tiles в состоянии.


const TileLoadMore = () => {

    const {loadMore} = useContext(TileContext);

    return (
        <Fragment>
            <button className="tile-load-more" 
            onClick={() => {

                loadMore();

            }}>
            Load more</button>
        </Fragment>

     );
}

FETCH CALL:


     componentDidUpdate(prevProps, prevState) {

        console.log('prevstate:', prevState.tileShowCount, 'currentstate:', this.state.tileShowCount);

        if(prevState.tiles !== this.state.tiles) {

            this.state.fetchData('/data/tileInfo.json')
            .then((res) => {
                this.setState( prevState => {
                        return {
                            tiles: res.slice(0, this.state.tileShowCount), 
                            loading: false
                        }
                    });
                })
            .catch((err) => {console.log(err);})

        } 

     }

Вот ссылка на мой проект: https://codesandbox.io/s/tiles-load-more-o2ub5

Заранее спасибо :)

1 Ответ

0 голосов
/ 13 марта 2020

В условии if, внутри componentDidUpdate() вы проверяете prevState.tiles !== this.state.tiles, это всегда будет верно в вашем случае, так как плитки - это массив объектов. В JavaScript массивы имеют значение Object, и оператор качества будет проверять, только если оба объекта имеют одинаковый экземпляр.

Пример: [] === [] всегда будет ложным.

Вам нужно будет обойти массив и проверить равенство на основе содержимого.

...