I'm using react-window
together with react-table
and when I type something in a cell, an then click on another cell, I have to click again to get the next cell focused so I can type. I don't think it has to do with key
- the usual case of react loosing focus. Almost sure it has to do with react-window
. When removing it, the issue is gone.
Focus is also being lost when I scroll with the mouse. So if I'm focused in a cell, and then scroll with the mouse wheel, it blures.
import React from 'react'
import { useTable } from 'react-table'
import { FixedSizeList } from 'react-window'
const EditableCell = ({
value: initialValue,
row: { index },
column: { id },
updateMyData,
}) => {
const [value, setValue] = React.useState(initialValue)
const onChange = e => setValue(e.target.value)
const onBlur = () => updateMyData(index, id, value)
React.useEffect(() => {setValue(initialValue)}, [initialValue])
return <input value={value} onChange={onChange} onBlur={onBlur} />
}
const defaultColumn = { Cell: EditableCell, width: 200,}
function Table({ columns, data, updateMyData }) {
const table = useTable({columns, data, defaultColumn, updateMyData})
const RenderRow = React.useCallback( ({ index, style }) => {
const row = table.rows[index]
table.prepareRow(row)
return (
<tr {...row.getRowProps({ style })} className="tr">
{row.cells.map(cell => (
<td {...cell.getCellProps()} className="td">
{cell.render('Cell')}
</td> ))}
</tr> )
}, [table.prepareRow, table.rows])
return (
<table {...table.getTableProps()}>
<tbody {...table.getTableBodyProps()}>
<FixedSizeList
height={400}
itemCount={table.rows.length}
itemSize={35}
width={table.totalColumnsWidth}
>
{RenderRow}
</FixedSizeList>
</tbody>
</table>
)
}
function App() {
const columns = React.useMemo(
() => [
{Header: 'Name',accessor: 'name',},
],
[]
)
const [data, setData] = React.useState(() => {return Array(1000).fill({name:'Jack'})})
const updateMyData = (rowIndex, columnId, value) => {
const temp = [...data]
temp[rowIndex]={...temp[rowIndex],[columnId]:value}
setData(temp)
}
return ( <Table columns={columns} data={data} updateMyData={updateMyData} /> )
}
export default App
Fixed by declaring the RenderItem component outside of the Table Component. So the component is not re-declared, but just the props are updating. (As recomended never to have child components declared inside Parent component)
import React from 'react'
import { useTable } from 'react-table'
import { FixedSizeList } from 'react-window'
const RenderRow = ({ index, style,data:{table} }) => {
const row = table.rows[index]
table.prepareRow(row)
return (
<tr {...row.getRowProps({ style })} className="tr">
{row.cells.map(cell => (
<td {...cell.getCellProps()} className="td">
{cell.render('Cell')}
</td> ))}
</tr> )
}
const EditableCell = ({
value: initialValue,
row: { index },
column: { id },
updateMyData,
}) => {
const [value, setValue] = React.useState(initialValue)
const onChange = e => setValue(e.target.value)
const onBlur = () => updateMyData(index, id, value)
React.useEffect(() => {setValue(initialValue)}, [initialValue])
return <input value={value} onChange={onChange} onBlur={onBlur} />
}
const defaultColumn = { Cell: EditableCell, width: 200,}
function Table({ columns, data, updateMyData }) {
const table = useTable({columns, data, defaultColumn, updateMyData})
return (
<table {...table.getTableProps()}>
<tbody {...table.getTableBodyProps()}>
<FixedSizeList
height={400}
itemData={{table}}
itemCount={table.rows.length}
itemSize={35}
width={table.totalColumnsWidth}
>
{RenderRow}
</FixedSizeList>
</tbody>
</table>
)
}
function App() {
const columns = React.useMemo(
() => [
{Header: 'Name',accessor: 'name',},
{Header: 'Age',accessor: 'age',},
],
[]
)
const [data, setData] = React.useState(() => {return Array(1000).fill({name:'Jack'})})
const updateMyData = (rowIndex, columnId, value) => {
const temp = [...data]
temp[rowIndex]={...temp[rowIndex],[columnId]:value}
setData(temp)
}
return ( <Table columns={columns} data={data} updateMyData={updateMyData} /> )
}
export default App