我正在使用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);
我希望状态更新,表更新并显示更新的数据。
答案 0 :(得分:0)
您是否在循环儿童上使用key
道具?在渲染函数中进行循环时,您需要向循环子项提供key
属性,以便React知道要更新哪些组件。
因此,在您的情况下,将是这样的:{data.map(n => <Component key={n.id} />)}
如果n
是具有唯一属性id
的对象。
答案 1 :(得分:0)
我能够使用redux来解决此问题并做出生命周期方法,
shouldComponentUpdate(nextProps, nextState){
if (this.state.data !== nextState.data){
this.setState({
data: nextState.data
})
return true
}
return false
}
这将比较当前状态和下一个状态。