React渲染表格时如何返回空tr元素解决ESLint返回值警告
问题说明
现有一段生成表格行(自定义DataRow对应原生tr元素)的代码逻辑如下:
const credentialRows = credentials.map((credential_record) => { if ( logic... ) { const credential_id = credential_record.credential_exchange_id const credentialState = credential_record.state.replaceAll('_', ' ') || '' const dateCreated = new Date(credential_record.created_at).toLocaleString() || '' let credentialName = '' if ( credential_record.credential_proposal_dict !== null && credential_record.credential_proposal_dict !== undefined ) { credentialName = credential_record.credential_proposal_dict.schema_name.replaceAll( '_', ' ' ) } return ( <DataRow key={credential_id} onClick={() => { openCredential(history, credential_id) }} > <DataCell>{credentialName}</DataCell> <DataCell className="title-case">{credentialState}</DataCell> <DataCell>{dateCreated}</DataCell> </DataRow> ) } // missing else here... })
生成的行元素作为tbody的子元素渲染,渲染逻辑如下:
<tbody>{credentialRows}</tbody>
当前代码功能运行无异常,但触发ESLint警告:
Expected to return a value at the end of arrow function
此前尝试的两种修复方案均存在问题:
- else分支返回空字符串:触发React子元素类型不合法报错
- else分支返回空
DataRow组件:被要求必须传入key属性,但占位空元素没有可用的key值
最佳实现方案
不需要返回空tr元素,两种合规方案可解决问题,优先选择第一种:
方案1(推荐):先过滤再映射
将条件判断从map回调中拆分出来,先用filter筛掉不需要渲染的记录,再对筛选后的列表做map生成行元素。从根源上避免回调分支无返回值的问题,也不会生成多余的占位节点,逻辑更清晰。
修正后代码:
const credentialRows = credentials .filter((credential_record) => { // 填入原if分支的判断逻辑,返回true的记录才会被渲染 return logic... }) .map((credential_record) => { const credential_id = credential_record.credential_exchange_id const credentialState = credential_record.state.replaceAll('_', ' ') || '' const dateCreated = new Date(credential_record.created_at).toLocaleString() || '' let credentialName = '' if ( credential_record.credential_proposal_dict !== null && credential_record.credential_proposal_dict !== undefined ) { credentialName = credential_record.credential_proposal_dict.schema_name.replaceAll( '_', ' ' ) } return ( <DataRow key={credential_id} onClick={() => { openCredential(history, credential_id) }} > <DataCell>{credentialName}</DataCell> <DataCell className="title-case">{credentialState}</DataCell> <DataCell>{dateCreated}</DataCell> </DataRow> ) })
方案2:不满足条件时返回null
如果不想拆分filter和map流程,直接在else分支返回null即可。React原生支持在渲染数组中返回null、undefined、布尔值,这类值不会生成真实DOM节点,不会触发子元素类型错误;且null不是React元素实例,不需要绑定key属性,不会触发key相关警告。
修正后代码仅需要在原if分支后补充返回值:
const credentialRows = credentials.map((credential_record) => { if (logic...) { // 原有逻辑不变,返回DataRow const credential_id = credential_record.credential_exchange_id const credentialState = credential_record.state.replaceAll('_', ' ') || '' const dateCreated = new Date(credential_record.created_at).toLocaleString() || '' let credentialName = '' if ( credential_record.credential_proposal_dict !== null && credential_record.credential_proposal_dict !== undefined ) { credentialName = credential_record.credential_proposal_dict.schema_name.replaceAll( '_', ' ' ) } return ( <DataRow key={credential_id} onClick={() => { openCredential(history, credential_id) }} > <DataCell>{credentialName}</DataCell> <DataCell className="title-case">{credentialState}</DataCell> <DataCell>{dateCreated}</DataCell> </DataRow> ) } // 不满足渲染条件直接返回null return null })
错误方案说明
- 返回空字符串不可行:字符串属于合法React子节点,会在tbody下生成多余文本节点,违反HTML表格内容规范,还可能导致布局异常
- 返回空DataRow不可行:只要返回组件实例就属于列表有效子节点,必须传入key,强行生成空tr还会占用行高出现无意义空白行,徒增DOM节点
内容的提问来源于stack exchange,提问作者Simon Nazarenko
相关产品推荐
相关产品推荐

