每次输入内容时功能组件都会重新渲染
functional component re-rendering every time I input something
我正在使用 react-table 版本 7。我正在使用全局过滤器进行过滤,我从沙箱中复制了一些代码并将其集成到我的代码中,这是我的 link复制代码 Open Sandbox。问题是每当我在搜索栏中写东西时,整个全局过滤器组件都会重新呈现并且输入字段失去焦点并且每次我都必须再次单击输入字段以输入文本,这非常烦人因为重新渲染需要时间,而且我每次都必须单击输入字段。为什么会发生这种情况以及为什么在 react-table 全局过滤器的沙箱示例中没有发生同样的事情。你可以看到上面的例子 link 我已经包含了。
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: <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;
我已经更正了你的完整代码。您没有使用沙盒中的 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;
我正在使用 react-table 版本 7。我正在使用全局过滤器进行过滤,我从沙箱中复制了一些代码并将其集成到我的代码中,这是我的 link复制代码 Open Sandbox。问题是每当我在搜索栏中写东西时,整个全局过滤器组件都会重新呈现并且输入字段失去焦点并且每次我都必须再次单击输入字段以输入文本,这非常烦人因为重新渲染需要时间,而且我每次都必须单击输入字段。为什么会发生这种情况以及为什么在 react-table 全局过滤器的沙箱示例中没有发生同样的事情。你可以看到上面的例子 link 我已经包含了。
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: <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;
我已经更正了你的完整代码。您没有使用沙盒中的 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;