React子组件删除最后一项后空状态不显示问题求助
问题:React子组件删除最后一项后空状态不显示
我有一个子组件,接收父组件传递的数组数据。数据展示、删除功能均正常,但删除表格最后一项后,空状态并未显示,仅在刷新页面后才会出现。我是React新手,可能尚未完全理解State/Props的管理逻辑,恳请各位帮忙解答,提前致谢。
父组件代码
import React from "react"; import { Message } from "semantic-ui-react"; import BasarService from "../../../../services/BasarService"; import BasarTable from "./components/BasarTable/BasarTable"; class Basars extends React.Component { constructor(props) { super(props); this.state = { error: null, isLoaded: false, basars: [] }; this.basarService = new BasarService(); this.deleteBasar = this.deleteBasar.bind(this); } deleteBasar(id) { this.basarService.delete(id, response => { var filteredBasars = this.state.basars.filter(basar => basar.id !== id); this.setState({ basars: filteredBasars }); console.log("Success:", response); }); } getBasars() { this.basarService.getAll(data => { this.setState({ isLoaded: true, basars: data }); }); } componentDidMount() { this.getBasars(); } render() { const { error, isLoaded, basars } = this.state; const ErrorMessage = () => ( <Message negative> <Message.Header>Basars could not be loaded!</Message.Header> <p>{error.message}</p> </Message> ); if (error) { return ErrorMessage(); } else if (!isLoaded) { return <div>Loading...</div>; } else { return ( <BasarTable basars={basars} deleteBasar={this.deleteBasar} /> ); } } } export default Basars;
子组件代码
import React from "react"; import { Table, Button, Icon } from "semantic-ui-react"; import { formatDate } from "../../../../../../util/timeFormat"; class BasarTable extends React.Component { constructor(props) { super(props); } handleClick(basarId) { this.props.deleteBasar(basarId); } render() { const { basars } = this.props; const BasarRows = basars => ( basars.map(basar => ( <Table.Row key={basar.id}> <Table.Cell>{basar.id}</Table.Cell> <Table.Cell>{basar.type}</Table.Cell> <Table.Cell>{formatDate(basar.startdate)}</Table.Cell> <Table.Cell>{formatDate(basar.enddate)}</Table.Cell> <Table.Cell> <Button icon color="red" onClick={() => this.handleClick(basar.id)}> <Icon name="trash" /> </Button> </Table.Cell> </Table.Row> )) ); const EmptyState = ( <Table.Row> <Table.Cell colSpan="5" textAlign="center"> <Icon name="frown" />No basars found! </Table.Cell> </Table.Row> ); return ( <Table celled> <Table.Header> <Table.Row> <Table.HeaderCell>ID</Table.HeaderCell> <Table.HeaderCell>Type</Table.HeaderCell> <Table.HeaderCell>StartDate</Table.HeaderCell> <Table.HeaderCell>EndDate</Table.HeaderCell> <Table.HeaderCell>Actions</Table.HeaderCell> </Table.Row> </Table.Header> <Table.Body> {basars ? BasarRows(basars) : EmptyState} </Table.Body> </Table> ); } } export default BasarTable;
问题分析与解决方案
嗨,我来帮你搞定这个问题~ 其实问题出在子组件里的一个小判断逻辑上:
你在子组件的Table.Body里写了:
{basars ? BasarRows(basars) : EmptyState}
在JavaScript里,空数组[]属于“真值”(truthy)——也就是说,哪怕数组里没有任何元素,basars的布尔值依然是true,所以这个判断永远会走BasarRows分支。而空数组调用map会返回空内容,导致表格body里啥都没有,自然看不到你写的EmptyState。
修复方法
把判断条件改成检查数组的长度是否大于0就好了:
修改子组件render方法里的Table.Body部分:
<Table.Body> {basars.length > 0 ? BasarRows(basars) : EmptyState} </Table.Body>
这样一来,当删除最后一项后,basars变成空数组(长度为0),就会自动渲染你定义的EmptyState,不需要刷新页面啦~
额外小优化
你还可以把BasarRows的定义简化一下,不用写成单独的函数,直接在JSX里处理:
render() { const { basars } = this.props; const EmptyState = ( <Table.Row> <Table.Cell colSpan="5" textAlign="center"> <Icon name="frown" />No basars found! </Table.Cell> </Table.Row> ); return ( <Table celled> {/* ... 表头部分不变 ... */} <Table.Body> {basars.length > 0 ? ( basars.map(basar => ( <Table.Row key={basar.id}> <Table.Cell>{basar.id}</Table.Cell> <Table.Cell>{basar.type}</Table.Cell> <Table.Cell>{formatDate(basar.startdate)}</Table.Cell> <Table.Cell>{formatDate(basar.enddate)}</Table.Cell> <Table.Cell> <Button icon color="red" onClick={() => this.handleClick(basar.id)}> <Icon name="trash" /> </Button> </Table.Cell> </Table.Row> )) ) : EmptyState} </Table.Body> </Table> ); }
这样代码会更简洁,逻辑也更直观~
另外补充一下:父组件删除数据后调用setState更新basars,React会自动触发子组件的重新渲染,所以只要判断逻辑正确,空状态会实时显示,不需要手动刷新页面哦~
内容的提问来源于stack exchange,提问作者Christopher Stöckl
相关产品推荐
相关产品推荐

