【问题标题】:functional component re-rendering every time I input something每次输入内容时功能组件都会重新渲染
【发布时间】:2020-04-24 15:50:46
【问题描述】:

我正在使用 react-table 版本 7。我正在使用全局过滤器进行过滤,我从沙箱中复制了一些代码并将其集成到我的中,这是我复制代码 Open Sandbox 的链接。问题是每当我在搜索栏中写一些东西时,整个全局过滤器组件都会重新渲染,并且输入字段失去焦点,而且每次我都必须再次单击输入字段才能输入文本,这很烦人因为重新渲染需要时间,而且我每次都必须单击输入字段。为什么会发生这种情况以及为什么在 react-table 全局过滤器的沙箱示例中没有发生同样的事情。您可以在我包含的上述链接中看到示例。

 return (
    <>
        <GlobalFilter
            preGlobalFilteredRows={preGlobalFilteredRows}
            globalFilter={state.globalFilter}
            setGlobalFilter={setGlobalFilter}
          />

        {/* //rest of the code*/}
         .....
    </> );

    function GlobalFilter({
      preGlobalFilteredRows,
      globalFilter,
      setGlobalFilter,
      }) {
    const count = preGlobalFilteredRows.length

    return (
      <span>
        Search:{' '}
        <input
          value={globalFilter || ''}
          onChange={e => {
            setGlobalFilter(e.target.value || undefined) // Set undefined to remove the filter entirely
          }}
          placeholder={`${count} records...`}
          style={{
            fontSize: '1.1rem',
            border: '0',
          }}
        />
      </span>
    )
  }


如果我直接在 return 语句中编写全局过滤器的代码,则不会发生此问题,使用它整个组件不会重新渲染。像这样。

return(
  <>
  div className="row" style={{ 'zoom': '94%' }}>
            <div className="col">
                <div class="student-search-field">
                    <h4>Search: &nbsp;<input
                        value={state.globalFilter || ""}
                        onChange={e => {
                            setGlobalFilter(e.target.value || undefined); // Set undefined to remove the filter entirely
                        }}
                        placeholder={`  ${count} Students..`}
                        style={{
                            fontSize: "1.1rem",
                            border: "1",

                        }}
                    /></h4>

                </div>


            </div>

        </div>
{/* //rest of the code*/}
</>);

我剩下的代码是这样的

她的就是我的完整代码。

import React from 'react';
import { useLocation } from "react-router-dom";
import { useTable, usePagination, useGlobalFilter } from 'react-table';

import './classdetails.css';


function SimpleTable(props) {

const location = useLocation();
var paginationDisplay = { display: '' };
console.log(location.state);
const data = React.useMemo(
    () => [
        {
            col1: 'john doe',
            col2: "world",

        },
        {
            col1: 'react-table',
            col2: 'rocks',
        },
        {
            col1: 'whatever',
            col2: 'you want',
        },
        {
            col1: 'whatever',
            col2: 'you want',
        },
        {
            col1: 'whatever',
            col2: 'you want',

        },
        {
            col1: 'whatever',
            col2: 'you want',

        },
        {
            col1: 'whatever',
            col2: 'you want',

        },
        {
            col1: 'whatever',
            col2: 'you want',

        },
        {
            col1: 'whatever',
            col2: 'you want',

        },

    ],
    [],
);
const columns = React.useMemo(
    () => [
        {
            Header: 'STUDENT NAME',
            accessor: 'col1', // accessor is the "key" in the data
            Cell: (row) => {
                return (
                    <>
                        {row.row.original.col1}
                        <p>FA16-BCS-067</p>
                    </>);
            },

        },
        {
            Header: 'ATTENDANCE',
            accessor: 'col2',// use accessor name in hidden column to hide a column e.g intitalstate.hiddenColumns['col2']
        },
        {
            Header: 'QUIZEZ',
            accessor: '',

        },
        {
            Header: 'ASSIGNMENT',
            accessor: '',
        },
        {
            Header: 'FIRST TERM',
            accessor: '',
        },
        {
            Header: 'MID TERM',
            accessor: '',

        },
        {
            Header: 'FINAL TERM',
            accessor: '',

        },
        {
            Header: 'action',
            accessor: '',
            Cell: (row) => {
                return (
                    <button className="btn btn-danger"
                        onClick={() => console.log(row.row)}
                    >
                        View
                    </button>);
            },

        },
    ],
    [],
);


  function GlobalFilter({
    preGlobalFilteredRows,
    globalFilter,
    setGlobalFilter,
  }) {
    const count = preGlobalFilteredRows.length

    return (
      <span>
        Search:{' '}
        <input
          value={globalFilter || ''}
          onChange={e => {
            setGlobalFilter(e.target.value || undefined) // Set undefined to remove the filter entirely
          }}
          placeholder={`${count} records...`}
          style={{
            fontSize: '1.1rem',
            border: '0',
          }}
        />
      </span>
    )
  }



const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    page,
    prepareRow,
    canPreviousPage,
    canNextPage,
    nextPage,
    previousPage,
    setPageSize,
    pageOptions,
    state,
    preGlobalFilteredRows,
    setGlobalFilter,
    state: { pageIndex, pageSize }

} = useTable({ columns, data, initialState: { pageIndex: 0, pageSize: 5, hiddenColumns: [''] } },
    useGlobalFilter, usePagination);



const count = preGlobalFilteredRows.length;
return (
    <>

        <GlobalFilter
            preGlobalFilteredRows={preGlobalFilteredRows}
            globalFilter={state.globalFilter}
            setGlobalFilter={setGlobalFilter}
          />


        {/* //table section */}

        <div className="row">
            <div className="col table-div-1 highlight table-2" style={{ 'overflowY': 'auto', 'height': '455px' }}>
                <table {...getTableProps()}>
                    <thead>
                        {headerGroups.map(headerGroup => (
                            <tr {...headerGroup.getHeaderGroupProps()}>
                                {headerGroup.headers.map(column => (
                                    <th
                                        {...column.getHeaderProps()}
                                    >
                                        {column.render('Header')}
                                    </th>
                                ))}
                            </tr>
                        ))}
                    </thead>
                    <tbody {...getTableBodyProps()}>
                        {page.map(row => {
                            prepareRow(row)
                            return (
                                <tr key={123} {...row.getRowProps()} >
                                    {row.cells.map(cell => {
                                        return (
                                            <td
                                                {...cell.getCellProps()}
                                                onClick={() => console.log()}
                                            >
                                                {cell.render('Cell')}
                                            </td>
                                        )
                                    })}
                                </tr>
                            )
                        })}
                    </tbody>
                </table>
            </div>
        </div>

        {/* //pagination section */}

    { props === props ? <>
        <div className="row pagination" style={paginationDisplay}>
            <span>
                Page{' '}
                <strong>
                    {pageIndex + 1} of {pageOptions.length}
                </strong>{' '}
            </span>
            <button className="btn btn-danger" onClick={() => previousPage()} disabled={!canPreviousPage}>
                {'<'}
            </button>{" "}
            <button className="btn btn-danger" onClick={() => nextPage()} disabled={!canNextPage}>
                {'>'}
            </button>{" "}
            <select className="btn btn-danger"
                value={pageSize}
                onChange={e => {
                    setPageSize(Number(e.target.value));
                    console.log(pageSize);
                }}
            >
                {[5, 10, 20, 30].map(pageSize => (
                    <option key={pageSize.value} value={pageSize}>
                        Show {pageSize}
                    </option>
                ))}
            </select>
        </div>
        </> : null }
    </>

);
   }

  export default SimpleTable;

【问题讨论】:

    标签: reactjs jsx react-table


    【解决方案1】:

    我已更正您的完整代码。您没有使用沙盒中的 Table 函数(从您复制代码的位置)。我测试了以下 工作正常 并满足您的要求。请看一下。

    import React from 'react';
    import {useTable, usePagination, useGlobalFilter} from 'react-table';
    import matchSorter from 'match-sorter'
    
    function SimpleTable(props) {
    
        var paginationDisplay = {display: ''};
    
        const data = React.useMemo(
            () => [
                {
                    col1: 'john doe',
                    col2: "world",
                },
                {
                    col1: 'react-table',
                    col2: 'rocks',
                },
                {
                    col1: 'whatever',
                    col2: 'you want',
                },
                {
                    col1: 'whatever',
                    col2: 'you want',
                },
                {
                    col1: 'whatever',
                    col2: 'you want',
                },
                {
                    col1: 'whatever',
                    col2: 'you want',
                },
                {
                    col1: 'whatever',
                    col2: 'you want',
                },
                {
                    col1: 'whatever',
                    col2: 'you want',
                },
                {
                    col1: 'whatever',
                    col2: 'you want',
                },
            ],
            [],
        );
    
        const columns = React.useMemo(
            () => [
                {
                    Header: 'STUDENT NAME',
                    accessor: 'col1', // accessor is the "key" in the data
                    Cell: (row) => {
                        return (
                            <>
                                {row.row.original.col1}
                                <p>FA16-BCS-067</p>
                            </>);
                    },
    
                },
                {
                    Header: 'ATTENDANCE',
                    accessor: 'col2',// use accessor name in hidden column to hide a column e.g intitalstate.hiddenColumns['col2']
                },
                {
                    Header: 'QUIZEZ',
                    accessor: '',
    
                },
                {
                    Header: 'ASSIGNMENT',
                    accessor: '',
                },
                {
                    Header: 'FIRST TERM',
                    accessor: '',
                },
                {
                    Header: 'MID TERM',
                    accessor: '',
                },
                {
                    Header: 'FINAL TERM',
                    accessor: '',
                },
                {
                    Header: 'action',
                    accessor: '',
                    Cell: (row) => {
                        return (
                            <button className="btn btn-danger"
                                    onClick={() => console.log(row.row)}
                            >
                                View
                            </button>);
                    },
                },
            ],
            [],
        );
    
        function GlobalFilter({
                                  preGlobalFilteredRows,
                                  globalFilter,
                                  setGlobalFilter,
                              }) {
            const count = preGlobalFilteredRows.length
    
            return (
                <span>
            Search:{' '}
                    <input
                        value={globalFilter || ''}
                        onChange={e => {
                            setGlobalFilter(e.target.value || undefined) // Set undefined to remove the filter entirely
                        }}
                        placeholder={`${count} records...`}
                        style={{
                            fontSize: '1.1rem',
                            border: '0',
                        }}
                    />
          </span>
            )
        }
    
    
        function fuzzyTextFilterFn(rows, id, filterValue) {
            return matchSorter(rows, filterValue, {keys: [row => row.values[id]]})
        }
    
        // Our table component
        function Table({columns, data}) {
            const filterTypes = React.useMemo(
                () => ({
                    // Add a new fuzzyTextFilterFn filter type.
                    fuzzyText: fuzzyTextFilterFn,
                    // Or, override the default text filter to use
                    // "startWith"
                    text: (rows, id, filterValue) => {
                        return rows.filter(row => {
                            const rowValue = row.values[id]
                            return rowValue !== undefined
                                ? String(rowValue)
                                    .toLowerCase()
                                    .startsWith(String(filterValue).toLowerCase())
                                : true
                        })
                    },
                }),
                []
            );
    
            const {
                getTableProps,
                getTableBodyProps,
                headerGroups,
                page,
                prepareRow,
                canPreviousPage,
                canNextPage,
                nextPage,
                previousPage,
                setPageSize,
                pageOptions,
                state,
                preGlobalFilteredRows,
                setGlobalFilter,
                state: {pageIndex, pageSize}
    
            } = useTable({columns, data, initialState: {pageIndex: 0, pageSize: 5, hiddenColumns: ['']}},
                useGlobalFilter, usePagination);
    
            const count = preGlobalFilteredRows.length;
            return (
                <>
                    <GlobalFilter
                        preGlobalFilteredRows={preGlobalFilteredRows}
                        globalFilter={state.globalFilter}
                        setGlobalFilter={setGlobalFilter}
                    />
    
                    {/* //table section */}
    
                    <div className="row">
                        <div className="col table-div-1 highlight table-2" style={{'overflowY': 'auto', 'height': '455px'}}>
                            <table {...getTableProps()}>
                                <thead>
                                {headerGroups.map(headerGroup => (
                                    <tr {...headerGroup.getHeaderGroupProps()}>
                                        {headerGroup.headers.map(column => (
                                            <th
                                                {...column.getHeaderProps()}
                                            >
                                                {column.render('Header')}
                                            </th>
                                        ))}
                                    </tr>
                                ))}
                                </thead>
                                <tbody {...getTableBodyProps()}>
                                {page.map(row => {
                                    prepareRow(row);
                                    return (
                                        <tr key={123} {...row.getRowProps()} >
                                            {row.cells.map(cell => {
                                                return (
                                                    <td
                                                        {...cell.getCellProps()}
                                                        onClick={() => console.log()}
                                                    >
                                                        {cell.render('Cell')}
                                                    </td>
                                                )
                                            })}
                                        </tr>
                                    )
                                })}
                                </tbody>
                            </table>
                        </div>
                    </div>
    
                    {/* //pagination section */}
    
                    {props === props ? <>
                        <div className="row pagination" style={paginationDisplay}>
                <span>
                    Page{' '}
                    <strong>
                        {pageIndex + 1} of {pageOptions.length}
                    </strong>{' '}
                </span>
                            <button className="btn btn-danger" onClick={() => previousPage()} disabled={!canPreviousPage}>
                                {'<'}
                            </button>
                            {" "}
                            <button className="btn btn-danger" onClick={() => nextPage()} disabled={!canNextPage}>
                                {'>'}
                            </button>
                            {" "}
                            <select className="btn btn-danger"
                                    value={pageSize}
                                    onChange={e => {
                                        setPageSize(Number(e.target.value));
                                        console.log(pageSize);
                                    }}
                            >
                                {[5, 10, 20, 30].map(pageSize => (
                                    <option key={pageSize} value={pageSize}>
                                        Show {pageSize}
                                    </option>
                                ))}
                            </select>
                        </div>
                    </> : null}
                </>
            );
        }
    
        return (
            <Table columns={columns} data={data}/>
        )
    }
    
    export default SimpleTable;
    

    【讨论】:

    • 它没有任何作用。 globalFilter 重新渲染。
    • @newbie,您能否提供完整的示例以便我们运行并重现您的问题?
    • 第三个代码块有完整的代码,你只需要渲染它,排除css文件就可以了。
    • @newbie,我已经更正并更新了我的答案。这是工作。请检查一下。
    • 它现在可以工作了,非常感谢。但是你能这么好心解释一下为什么每次我在里面写东西时全局过滤器都不会重新渲染吗?我有点困惑,为什么它在之前而不是现在重新渲染。
    猜你喜欢
    • 2021-10-16
    • 2021-06-23
    • 2022-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 2021-10-15
    相关资源
    最近更新 更多