如何在表格中访问Formik Field组件当前值并按行区分
解决表格行内Formik Field值获取与区分问题
问题根源
你当前的写法存在两个核心问题:
- 每行单独创建一个Formik实例,按钮位于Formik组件外部,无法直接访问Formik内部的字段状态
- 所有Field的
name都设为tokenAmount,没有区分不同行的输入,导致无法精准获取对应行的值
解决方案
将Formik实例提升到表格外层,统一管理所有行的输入状态,同时给每行的Field设置唯一的name标识:
1. 重构Formik结构与初始值
把Formik包裹在整个表格外面,初始化时根据token列表生成对应行的输入值:
<Formik initialValues={{ // 用token的id作为key,初始化每行的tokenAmount为0 tokenAmounts: tokens.reduce((acc, token) => { acc[token.id] = 0; return acc; }, {}) }} > {({ values }) => ( <Form> <Table> {/* 表格表头... */} <TableBody> {tokens.map((token) => { const isItemSelected = // 你的选中逻辑 const labelId = // 你的labelId逻辑 return ( <TableRow hover key={token.id} sx={{ '&:last-child td, &:last-child th': { border: 0 } }} selected={isItemSelected} onClick={(event) => handleClick(event, token.address, 0, 0, "0")} > <TableCell padding="checkbox"> <Checkbox color="primary" checked={isItemSelected} inputProps={{ 'aria-labelledby': labelId, }} /> </TableCell> <TableCell align="center">{token.name}</TableCell> <TableCell align="center">{token.symbol}</TableCell> <TableCell align="center">{token.address}</TableCell> <TableCell align="center">{token.maxAmount}</TableCell> <TableCell align="center"> {/* 用token.id作为name的唯一标识 */} <Field id={`tokenAmount-${token.id}`} name={`tokenAmounts.${token.id}`} type="number" disabled={false} /> </TableCell> <TableCell align="center"> <Button disabled={!isItemSelected} onClick={() => { // 从Formik的values中获取当前行对应的tokenAmount值 const amount = values.tokenAmounts[token.id]; approveERC20Token(token.address, props.smartVaultContract, amount); }} color="primary" variant="contained" > Approve </Button> </TableCell> </TableRow> ); })} </TableBody> </Table> </Form> )} </Formik>
2. 关键改动说明
- 统一Formik实例:将Formik移到表格外层,所有行的输入都由同一个Formik管理,避免了实例隔离的问题
- 唯一字段标识:每行Field的
name设为tokenAmounts.${token.id},利用Formik的嵌套对象语法区分不同行的输入值 - 直接从values取值:按钮点击时,通过Formik暴露的
values对象,根据当前token的id精准获取对应行的输入值
备选方案:使用Formik Context(适合复杂组件结构)
如果你的表格行是独立组件,可以通过useFormikContext钩子在子组件中获取Formik的上下文:
// 表格行组件内部 import { useFormikContext } from 'formik'; const TokenTableRow = ({ token, isItemSelected, labelId, handleClick, approveERC20Token, smartVaultContract }) => { const { values } = useFormikContext(); return ( <TableRow // ...其他属性 > {/* ...其他单元格 */} <TableCell align="center"> <Field id={`tokenAmount-${token.id}`} name={`tokenAmounts.${token.id}`} type="number" disabled={false} /> </TableCell> <TableCell align="center"> <Button disabled={!isItemSelected} onClick={() => { const amount = values.tokenAmounts[token.id]; approveERC20Token(token.address, smartVaultContract, amount); }} color="primary" variant="contained" > Approve </Button> </TableCell> </TableRow> ); };
内容的提问来源于stack exchange,提问作者Falcon Stakepool
相关产品推荐
相关产品推荐

