如何在React Hooks中为表格添加行且避免出现重复行?
问题原因
- 闭包旧值问题:你更新
tableRows时直接使用了当前作用域捕获的tableRows,而getCurrentPrice是异步函数,接口返回时如果组件已经触发过重渲染,当前作用域里的tableRows还是旧值,拼接后就会出现旧数据重复插入的情况。 - 全局索引异常:
tableRowIndex定义在组件外部属于全局变量,组件多次挂载、卸载都会导致计数异常;同时你渲染TableRow时错误将全局tableRowIndex作为所有行的key属性值,React检测到key重复就会出现渲染异常,产生重复行。 - 直接修改入参:你直接修改了传入的
inputs对象的属性,属于引用对象修改,也可能引发意外的状态异常。
修复方案
核心改动点
- state更新改用函数式写法,直接拿到最新的state值,规避闭包旧值问题
- 行索引移入组件内部用
useRef存储,避免全局污染,同时渲染时绑定每行自身的index作为key - 新增行时生成新的对象,不直接修改入参
inputs
修复后完整代码
import { useState, useRef } from 'react'; import axios from 'axios'; const CoinTable = () => { const baseURL = 'endpoint/'; const [tableRows, setRows] = useState([] as any); // 行索引用useRef存储,重渲染不会重置,也不会污染全局 const tableRowIndexRef = useRef(0); const getCurrentPrice = async (inputs: any) => { const response = await axios.get(`${baseURL}${inputs.currency}/USD`) const currentPrice = response.data // 生成新行对象,不直接修改入参 const newRow = { ...inputs, cryptoPrice: currentPrice.rate, amtCrypto: (inputs.amount / currentPrice.rate).toFixed(8), index: ++tableRowIndexRef.current } addNewRow(newRow) } const addNewRow = (newRow: any) => { // 函数式更新获取最新的rows列表 setRows(prevRows => [...prevRows, newRow]) } const rows = tableRows.map((row: any) => { return ( <TableRow key={row.index} // 绑定当前行自身的index作为key addNewRow={addNewRow} removeRow={removeRowHandler} getCurrentPrice={getCurrentPrice} row={row} /> ) }) return ( <> <AddItem getCurrentPrice={getCurrentPrice} /> {tableRows.length > 0 && <table> <tbody> <tr> <th>Merchant</th> <th>Item</th> <th>Amount(Crypto)</th> <th>Currency</th> <th>Price/crypto(USD)</th> <th>Amount(USD)</th> </tr> {rows} </tbody> </table> } </> ) } export default CoinTable;
内容的提问来源于stack exchange,提问作者LDB
相关产品推荐
相关产品推荐

