状态更新,但表格不会重新呈现/更新

时间:2019-04-02 12:11:51

标签: javascript reactjs

我正在使用Django通道来更新我的React表。通道工作正常,并发送更新以作出反应。收到更新后,我将更新反应状态,但表不会更新或重新呈现以显示添加的数据。

我已经在控制台上记录了从通道和React状态获得的数据,它可以完美更新,我也尝试过使用诸如lifecomponentcomponentupdate和componentdidupdate之类的React生命周期,但是状态可以完美更新,但是表却不是

这是我更新状态的方式:

addMessage(message) {
  console.log("message")
  this.setState({
    data: [...this.state.data, message]
  })
}
setMessages(messages) {
  console.log(messages)
  this.setState({ data: messages })
}

这是表格外观的摘要

render(){
  const {data} = this.state
  console.log(data) //shows updated data at every update
  return(
    <table>
      {data.map(n => {
        return(
          <tr key={n.id}>
             <td> {n.name} </td>
             <td> {n.found} </td>
             <td> {n.date} </td>
          </tr>
      )})}

</table>
)}

这是所要求的完整组件(太长了,这就是我最小化它的原因)

class EnhancedTable extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      order: 'asc',
      orderBy: 'calories',
      selected: [],
      data:[],
      message: [],
      messages: [],
      page: 0,
      rowsPerPage: 50,
      expanded: false,
      search:''
    };
    this.waitForSocketConnection(() => {
      WebSocketInstance.addCallbacks(this.setMessages.bind(this), this.addMessage.bind(this));
      WebSocketInstance.newChatMessage(this.props.message)
      WebSocketInstance.fetchMessages()

    })

  }



waitForSocketConnection(callback) {
  const component = this;
  setTimeout(
    function () {
      if (WebSocketInstance.state() === 1) {
        console.log('connection is secure');

        callback()

        return;
      } else {
        console.log('waiting for connection')
        component.waitForSocketConnection(callback)
      }
    }, 100);
}

addMessage(message) {
  console.log("message")
  let newData = [...this.state.data, message]
  this.setState({

    data: newData
  })
}
setMessages(messages) {
  console.log(messages)
  this.setState({ data: messages })
}

componentDidMount() {
  WebSocketInstance.connect()
}


  handleRequestSort = (event, property) => {
    const orderBy = property;
    let order = 'desc';

    if (this.state.orderBy === property && this.state.order === 'desc') {
      order = 'asc';
    }

    this.setState({ order, orderBy });
  };

  handleSelectAllClick = event => {
    if (event.target.checked) {
      this.setState(state => ({ selected: state.data.map(n => n.id) }))
      return;
    }
    this.setState({ selected: [] });
  };

  handleAddClick = () => event => {
    const selected = this.state.selected
    selected.forEach(function (element) {
      axios.put(`${process.env.REACT_APP_DEV_API_URL}/api/main/${element}/`, {
        relevance: true
      })
        .then((response) =>
          console.log(response)
        )
        .catch(function (error) {
          console.log(error)
        })

    }
    )

  }

  handleClick = (event, id) => {
    const { selected } = this.state;
    const selectedIndex = selected.indexOf(id);
    let newSelected = [];

    if (selectedIndex === -1) {
      newSelected = newSelected.concat(selected, id);
    } else if (selectedIndex === 0) {
      newSelected = newSelected.concat(selected.slice(1));
    } else if (selectedIndex === selected.length - 1) {
      newSelected = newSelected.concat(selected.slice(0, -1));
    } else if (selectedIndex > 0) {
      newSelected = newSelected.concat(
        selected.slice(0, selectedIndex),
        selected.slice(selectedIndex + 1),
      );
    }

    this.setState({ selected: newSelected });
  };

  handleChangePage = (event, page) => {
    this.setState({ page });
  };

  handleChangeRowsPerPage = event => {
    this.setState({ rowsPerPage: event.target.value });
  };

  handleChange = panel => (event, expanded) => {
    this.setState({
      expanded: expanded ? panel : false,
    });
  };


  isSelected = id => this.state.selected.indexOf(id) !== -1;

  render() {
    const { classes } = this.props;
    const { order, orderBy, selected, rowsPerPage, page, data, expanded } = this.state;
    const emptyRows = rowsPerPage - Math.min(rowsPerPage, data.length - page * rowsPerPage);
    // const { expanded } = this.state;
   console.log(data)
    return (
      <Paper className={classes.root}>
        <EnhancedTableToolbar numSelected={selected.length} handleAddClick={this.handleAddClick()} />
        <div className={classes.tableWrapper}>
          <Table className={classes.table} aria-labelledby="tableTitle">
            <EnhancedTableHead
              numSelected={selected.length}
              order={order}
              orderBy={orderBy}
              onSelectAllClick={this.handleSelectAllClick}
              onRequestSort={this.handleRequestSort}
              rowCount={data.length}
            />
            <TableBody>

              {stableSort(data, getSorting(order, orderBy))
                .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
                .map(n => {
                  const isSelected = this.isSelected(n.id);
                  return (
                    <TableRow
                      hover

                      key={n.id}

                    >
                      <TableCell padding="checkbox" onClick={event => this.handleClick(event, n.id)}
                        role="checkbox"
                        aria-checked={isSelected}
                        tabIndex={-1}
                        key={n.id}
                        selected={isSelected}>
                        <Checkbox checked={n.relevance === true ? true : false} classes={{
                          root: classes.root,

                        }} />
                      </TableCell>
                      <TableCell component="th" scope="row" padding="none" style={{ color: "#1565C0" }}>
                        <a href={`${n.url}`} target="_blank" rel='noopener noreferrer'>{expanded === false ? `${n.url.slice(0, 30)}` : `${n.url}`}</a>

                      </TableCell>
                      <TableCell component="th" scope="row" padding="none">{n.keyword}</TableCell>
                      <TableCell component="th" scope="row" padding="none"><ExpansionPanel
                        square
                        expanded={expanded === `${n.id}`}
                        onChange={this.handleChange(`${n.id}`)}
                      >
                        <ExpansionPanelSummary>
                          <Typography style={{ color: `${n.keyword ? 'red' : 'none'}` }}>{n.source.slice(1, 100)}...</Typography> <Button color="primary" style={{ padding: '0px' }}>{expanded === false ? 'Read More' : 'Read Less'}</Button>
                        </ExpansionPanelSummary>
                        <ExpansionPanelDetails>
                          <div>
                            {n.source.split(',').map(element => {
                              return (<Typography key={Math.random()} >{element.replace(n.keyword, n.keyword.toUpperCase())}</Typography>)
                            })}

                          </div>


                        </ExpansionPanelDetails>
                      </ExpansionPanel>

                      </TableCell>
                      <TableCell align="right">{n.found}</TableCell>
                      <TableCell align="right">
                        {n.severityLevel === 'low' ?
                          <Badge className={classes.margin} badgeContent={"Low"} color="primary">
                            <CloudCircle />
                          </Badge>
                          :
                          <Badge className={classes.margin} badgeContent={"High"} color="secondary">
                            <AddCircleIcon />
                          </Badge>}
                      </TableCell>
                      <TableCell align="right" style={{ color: "#2E7D32" }}>{n.timestamp}</TableCell>
                    </TableRow>
                  );
                })}
              {emptyRows > 0 && (
                <TableRow style={{ height: 49 * emptyRows }}>
                  <TableCell colSpan={6} />
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>
        <TablePagination
          rowsPerPageOptions={[5, 10, 25]}
          component="div"
          count={data.length}
          rowsPerPage={rowsPerPage}
          page={page}
          backIconButtonProps={{
            'aria-label': 'Previous Page',
          }}
          nextIconButtonProps={{
            'aria-label': 'Next Page',
          }}
          onChangePage={this.handleChangePage}
          onChangeRowsPerPage={this.handleChangeRowsPerPage}
        />
      </Paper>
    );
  }
}

EnhancedTable.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(EnhancedTable);

我希望状态更新,表更新并显示更新的数据。

2 个答案:

答案 0 :(得分:0)

您是否在循环儿童上使用key道具?在渲染函数中进行循环时,您需要向循环子项提供key属性,以便React知道要更新哪些组件。 因此,在您的情况下,将是这样的:{data.map(n => <Component key={n.id} />)}如果n是具有唯一属性id的对象。

反应关键道具:https://reactjs.org/docs/lists-and-keys.html#keys

答案 1 :(得分:0)

我能够使用redux来解决此问题并做出生命周期方法,

 shouldComponentUpdate(nextProps, nextState){
if (this.state.data !== nextState.data){
  this.setState({
    data: nextState.data
  })
  return true
}
return false

}

这将比较当前状态和下一个状态。