React Hook useEffect () работает непрерывно, хотя я передаю второй параметр - PullRequest
0 голосов
/ 31 января 2020

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

Если я передам весь объект pagination вторым параметрам функции useEffect(), то fetchData() будет вызываться непрерывно. Если я только передам pagination.current_page, он будет вызываться только один раз, но когда я установлю новую pagination, как вы видите в функции navigatePage(), useEffect() не вызывает fetchData(), хотя pagination изменилось.

Как это решить. Большое спасибо!

Кроме того, я не хочу использовать вызов useEffect() при первом подключении компонента, потому что items получен от реквизита (Это выборка сервером, это следующий js проект ).

import React, {useEffect, useState} from 'react';
import Filter from "../Filter/Filter";
import AdsListingItem from "../AdsListingItem/AdsListingItem";
import {Pagination} from "antd-mobile";

import styles from './AdsListing.module.css';

import axios from 'axios';

const locale = {
    prevText: 'Trang trước',
    nextText: 'Trang sau'
};

const AdsListing = ({items, meta}) => {

    const [data, setData] = useState(items);

    const [pagination, setPagination] = useState(meta);

    const {last_page, current_page} = pagination;

    const fetchData = async (params = {}) => {
        axios.get('/ads', {...params})
            .then(({data}) => {
                setData(data.data);
                setPagination(data.meta);
            })
            .catch(error => console.log(error))
    };

    useEffect( () => {
        fetchData({page: pagination.current_page});
    }, [pagination.current_page]);

    const navigatePage = (pager) => {
        const newPagination = pagination;
        newPagination.current_page = pager;
        setPagination(newPagination);
    };

    return (
        <>
            <Filter/>
            <div className="row  no-gutters">
                <div className="col-md-8">
                    <div>
                        {data.map(item => (
                            <AdsListingItem key={item.id} item={item}/>
                        ))}
                    </div>
                    <div className={styles.pagination__container}>
                        <Pagination onChange={navigatePage} total={last_page} current={current_page} locale={locale}/>
                    </div>
                </div>
                <div className="col-md-4" style={{padding: '15px'}}>
                    <img style={{width: '100%'}} src="https://tpc.googlesyndication.com/simgad/10559698493288182074"
                         alt="ads"/>
                </div>
            </div>


        </>
    )
};

export default AdsListing;

1 Ответ

0 голосов
/ 31 января 2020

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

const navigatePage = (pager) => {
  const newPagination = pagination; // copy ref pointing to pagination
  newPagination.current_page = pager; // mutate property on ref
  setPagination(newPagination); // save ref still pointing to pagination
};

В этом случае место в памяти, которое равно pagination, остается прежним. c. Вместо этого вы должны скопировать все pagination свойства в новый объект.

const navigatePage = (pager) => {
  const newPagination = {...pagination}; // shallow copy into new object
  newPagination.current_page = pager;
  setPagination(newPagination); // save new object
};

Чтобы продвинуться дальше, вы действительно должны выполнять функциональные обновления для правильной очереди обновлений , Это в том случае, если setPagination вызывается несколько раз в течение одного цикла рендеринга.

const navigatePage = (pager) => {
  setPagination(prevPagination => {
    const newPagination = {...prevPagination};
    newPagination.current_page = pager;
  });
};

В случае обновлений в очереди с нумерацией страниц может не представлять проблемы (последняя текущая страница set выигрывает следующую битву рендеринга), но если какие-либо обновления состояния на самом деле зависят от предыдущего значения, тогда определенно используйте шаблон функционального обновления

...