簡體   English   中英

Uncaught Invariant Violation:重新渲染太多。 React 限制渲染次數以防止分頁出現無限循環

[英]Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop in pagination

我在表格中有一個數據,我想向它添加一個分頁選項。 在用戶界面中,用戶應該能夠選擇每頁的數據和頁面索引,這就是為什么我向它添加了一些句柄方法並嘗試渲染它,但我遇到了上述錯誤。

整個 jsx 文件太長,無法共享,因此我只共享對我來說很重要的代碼,並將其他代碼替換為...如果您需要其他任何內容,可以在評論中提出。

function Activity(props) {
...
const variables = useMemo(() => ({
    projectId,
    language,
    env: environment,
    pageSize: 20,
    filter,
    ...getSortFunction(),
}), [projectId, language, environment, filter, getSortFunction()]);

const {
    data, hasNextPage, loading, loadMore, refetch,
} = useActivity(variables);

//pagination section

const [pagination, setPagination] = useState({
    currentPage: 1,
    dataPerPage: 10,
    indexOfLastData: 9,
    indexOfFirstData: 0,
})

const [totalPages, setTotalPages] = useState(1);

const [paginationString, setPaginationString] = useState(`Current page ${pagination.currentPage}, total number of data ${pagination.dataPerPage}`)

const handlePagination = (page, dataPerPage, currentPagination) => {
    if (currentPagination.currentPage != page) handlePaginationCurrentPage(page, currentPagination);
    if (currentPagination.dataPerPage != dataPerPage) handlePaginationDataPerPage(dataPerPage, currentPagination);
    const dataToBeUsed = [...data].slice(pagination.indexOfFirstData, pagination.indexOfLastData);
    setTotalPages(Math.ceil(3 / pagination.dataPerPage));
    return dataToBeUsed;
}

const handlePaginationString = () => {
    setPaginationString(`current page ${pagination.currentPage}, total number of data ${pagination.dataPerPage}`)
}

const handlePaginationCurrentPage = (page, pagination) => {
    useEffect(() => {
        setPagination({
            ...pagination,
            currentPage: Number(page),
            indexOfLastData: pagination.dataPerPage * Number(page) - 1,
            indexOfFirstData: pagination.dataPerPage * Number(page) - pagination.dataPerPage
        })
    })
}

const handlePaginationDataPerPage = (dataPerPage, pagination) => {
    useEffect(() => {
        setPagination({
            ...pagination,
            dataPerPage: dataPerPage,
            indexOfLastData: dataPerPage * pagination.currentPage - 1,
            indexOfFirstData: dataPerPage * pagination.currentPage - pagination.dataPerPage
        })
    })
}

const resetPagination = (e) => {
    e.stopPropagation();
    handlePagination(1, 10, pagination);
};
...
const renderActions = row => (
    <ActivityActionsColumn
        outdated={ isUtteranceOutdated(row.datum) }
        datum={ row.datum }
        handleSetValidated={ handleSetValidated }
        onDelete={ handleDelete }
        onMarkOoS={ handleMarkOoS }
        data={ handlePagination(1, 10, pagination) }
        getSmartTips={ utterance => getSmartTips({
            nluThreshold, endTime, examples, utterance,
        }) }
    />
);

...

const columns = [
    { key: '_id', selectionKey: true, hidden: true },
    {
        key: 'confidence',
        style: { width: '51px', minWidth: '51px' },
        render: renderConfidence,
    },
    {
        key: 'intent',
        style: { width: '180px', minWidth: '180px', overflow: 'hidden' },
        render: renderIntent,
    },
    {
        key: 'conversation-popup', style: { width: '30px', minWidth: '30px' }, render: renderConvPopup,
    },
    {
        key: 'text',
        style: { width: '100%' },
        render: renderExample,
    },
    ...(can('incoming:w', projectId) ? [
        {
            key: 'actions',
            style: { width: '110px' },
            render: renderActions,
        },
    ] : []),
];
const renderTopBar = () => (
    <div className='side-by-side wrap' style={ { marginBottom: '10px' } }>
        ...
        <Accordion className='pagination-accordion'>
            <Accordion.Title
                active={ activeAccordion }
                onClick={ () => handleAccordionClick() }
                data-cy='toggle-pagination'
                className='pagination-accordian-title'
            >
                <Icon name='dropdown' />
                <span className='toggle-pagination'>
                    { activeAccordion
                        ? `Hide Pagination Options `
                        : `Show Pagination Options ` }
                </span>
                <span className="toggle-pagination pagination-string">
                    { activeAccordion
                        ? `${paginationString}`
                        : `${paginationString}` }
                </span>
                {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */ }
                <span
                    data-cy='reset-pagination'
                    onClick={ e => resetPagination(e) }
                    role='button'
                    tabIndex='0'
                    className='reset-button'
                >
                    <Icon name='redo' size='small' /> Reset
                </span>
            </Accordion.Title>
        </Accordion>
    </div>
);
return (
    <>
        { !!openConvPopup && <ConversationSidePanel utterance={ openConvPopup } onClose={ () => setOpenConvPopup(false) } /> }
        { renderTopBar() }
        { data && data.length ? (
            <>
                <DataTable
                    ref={ tableRef }
                    columns={ columns }
                    data={ handlePagination(1, 10, pagination) }
                    hasNextPage={ hasNextPage }
                    loadMore={ loading ? () => { } : loadMore }
                    onScroll={ handleScroll }
                    selection={ selection }
                    onChangeSelection={ (newSelection) => {
                        setSelection(newSelection);
                        setOpenConvPopup(false);
                    } }
                />
)}

我不能在分頁中使用數據,因為它在很多地方都使用過,並且在那些地方,所有設計的假設數據都是全長的,所以我應該單獨使用它(例如/在 handlePagination 中我使用 data.slice() function)

謝謝!

我變了

<DataTable
                ref={ tableRef }
                columns={ columns }
                data={ handlePagination(1, 10, pagination) }
                hasNextPage={ hasNextPage }
                loadMore={ loading ? () => { } : loadMore }
                onScroll={ handleScroll }
                selection={ selection }
                onChangeSelection={ (newSelection) => {
                    setSelection(newSelection);
                    setOpenConvPopup(false);
                } }
            />

<DataTable
                ref={ tableRef }
                columns={ columns }
                data={ dataToBeShowed }
                hasNextPage={ hasNextPage }
                loadMore={ loading ? () => { } : loadMore }
                onScroll={ handleScroll }
                selection={ selection }
                onChangeSelection={ (newSelection) => {
                    setSelection(newSelection);
                    setOpenConvPopup(false);
                } }
            />

並添加

const [dataToBeShowed, setDataToBeShowed] = useState(data.slice(pagination.indexOfFirstData, pagination.indexOfLastData));
useEffect(() => {
    setDataToBeShowed(data.slice(pagination.indexOfFirstData, pagination.indexOfLastData));
    setPaginationString(`Current page ${pagination.currentPage}, total number of data ${pagination.dataPerPage}`)
    setTotalPages(Math.ceil(data.length / pagination.dataPerPage));

}, [data, pagination.indexOfFirstData, pagination.indexOfLastData]);

這解決了,因為我看到 handlePagination(1, 10, pagination) 不在 Activity 中呈現,而是在 Window 中呈現,這意味着它看不到狀態,因此我添加了 dataToBeShown 並將其分配給真實數據,因為我添加了 useEffect,它跟隨數據(真實數據)的變化。

(如果您使用 onClick 與您可以簡單地添加 () => {handleOnBruh()} 相比,它會以這種方式將自身與文件綁定。)

謝謝!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM