You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:49:28