Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/422.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如果道具更改,React.memo不会重新渲染_Javascript_Reactjs_React Memo - Fatal编程技术网

Javascript 如果道具更改,React.memo不会重新渲染

Javascript 如果道具更改,React.memo不会重新渲染,javascript,reactjs,react-memo,Javascript,Reactjs,React Memo,我试图从头开始创建一个表组件,使用React memo组件作为行来防止不必要的重新呈现。 “行”单元格是从子函数创建的React组件数组,该子函数使用行数据、行id、行索引和commitChange函数作为参数。 commitChange函数用于设置行的表状态。 代码如下: <Table data={[{name: 1}, {name: 2}]}> {({data, index, id, commitChange})=>

我试图从头开始创建一个表组件,使用React memo组件作为行来防止不必要的重新呈现。 “行”单元格是从子函数创建的React组件数组,该子函数使用行数据、行id、行索引和commitChange函数作为参数。 commitChange函数用于设置行的表状态。 代码如下:

<Table data={[{name: 1}, {name: 2}]}>
            {({data, index, id, commitChange})=>
                [
                <div>Name: {data.name}</div>,
                <TextBox value={data.name} onChange={(value)=>commitChange('name', parseInt(value, 10))}/>,
                <TextBox value={data.place}/>
                ]
            }
 </Table>

{({data,index,id,commitChange})=>
[
名称:{data.Name},
commitChange('name',parseInt(value,10))}/>,
]
}
TableComponents.jsx

export const Table = ({ data: initialData, maxRows = 10, children: makeChildren, primaryKey = 'ID' }) => {
const [TableData, setTableData] = useState(initialData);
console.log('table re-render')

useEffect(() => {
    console.log('--->table data', TableData)
}, [TableData]);

useEffect(() => {
    setTableData(initialData)
}, [initialData]);

const renderCells = useCallback((param) => {
    return makeChildren(param)
}, [])

const commitChange = useCallback((field, value, index) => {
    setTableData(prevTableData => {
        const newState = Array.from(prevTableData)
        newState[index][field] = value
        return [...newState]
    })
}, [])

const renderRows = () => {
    return TableData.map((row, i) =>
        <TableRow
            key={row[primaryKey]}
            index={i}
            rowData={row}
            cells={renderCells}
            id={row[primaryKey]}
            updateTableData={commitChange}
        />
    )
}

//
return (
    <table>
        <tbody>
            {
                renderRows()
            }
        </tbody>
    </table>
  );
}

const TableRow = React.memo(({ index, rowData, cells, id, updateTableData }) => {

console.log('render row' + index, rowData)

useEffect(() => {
    console.log('row ' + index + ' data', rowData)
}, [rowData])


const renderCells = () => {
    return cells({ data: rowData, index, id, commitChange: (field, value) => updateTableData(field, value, index) }).map((c, i) => {
        return (
            <td key={i}>
                {c}
            </td>
        )
    })
}

return (
    <tr>
        {renderCells()}
    </tr>
)
})
export const Table=({data:initialData,maxRows=10,children:makeChildren,primaryKey='ID'})=>{
const[TableData,setTableData]=使用状态(initialData);
console.log('表重新呈现')
useffect(()=>{
console.log('-->table data',TableData)
},[TableData]);
useffect(()=>{
setTableData(初始数据)
},[初始数据];
const renderCells=useCallback((参数)=>{
返回makeChildren(param)
}, [])
const commitChange=useCallback((字段、值、索引)=>{
setTableData(prevTableData=>{
const newState=Array.from(prevTableData)
newState[索引][字段]=值
返回[…新闻状态]
})
}, [])
const renderRows=()=>{
返回TableData.map((行,i)=>
)
}
//
返回(
{
renderRows()
}
);
}
const TableRow=React.memo({index,rowData,cells,id,updateTableData})=>{
log('render row'+索引,rowData)
useffect(()=>{
console.log('行'+索引+'数据',行数据)
},[rowData])
const renderCells=()=>{
返回单元格({data:rowData,index,id,commitChange:(字段,值)=>updateTableData(字段,值,索引)}).map((c,i)=>{
返回(
{c}
)
})
}
返回(
{renderCells()}
)
})
将元素添加到表组件上的数据道具时,表将重新渲染并仅渲染添加的行,这样可以正常工作

但是,当从第二个单元格中的文本框编辑行元素时,父表组件上的数据已正确更新,但行未重新呈现。 当我使用React.memo areEqual函数()检查传递给组件的previus和next属性时,数据属性是相同的。 在逐行更新TableData并执行renderRows函数但不重新呈现更新的行时,将重新呈现table组件

有什么问题?谢谢你的帮助


p.S否我不希望外部库生成自定义表元素

问题是您正在浅层复制表数据(使用
),因此当您在此处更新值时:

newState[index][field] = value
。。。您正在修改数组中的项,但对该项的引用保持不变。解决方法之一是:

setTableData(prevTableData =>
    prevTableData.map((item, i) =>
      i === index ? { ...item, [field]: value } : item,
    ),
  )
因此,现在在更新字段时会创建一个新对象