Estoy usando react-window de react-table y cuando escribo algo en una celda y luego hago clic en otra celda, tengo que hacer clic nuevamente para enfocar la siguiente celda y poder escribir. No creo que tenga que ver con la key , el caso habitual de reacción que pierde el foco. Casi seguro que tiene que ver con react-window . Al quitarlo, el problema desaparece.
El foco también se pierde cuando me desplazo con el mouse. Entonces, si estoy enfocado en una celda y luego me desplazo con la rueda del mouse, se vuelve borroso.
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 AppSe solucionó declarando el componente RenderItem fuera del componente de tabla. Por lo tanto, el componente no se vuelve a declarar, sino que solo se actualizan los accesorios. (Como se recomienda nunca tener componentes secundarios declarados dentro del componente principal)
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