【发布时间】:2020-02-21 11:07:56
【问题描述】:
我为论坛视图创建了一个 React 组件。
在几个不同论坛的顶部有一些标签。
当我们单击选项卡时,state forumID 用于检查单击了哪个选项卡以及应该显示哪个论坛。
state discussions 用于存储论坛的内容。
state isLoading 用于标记请求何时发送到服务器。
import React from 'react'
// nodejs library that concatenates classes
import classNames from 'classnames'
// @material-ui/core components
import withStyles from '@material-ui/core/styles/withStyles'
import Tooltip from '@material-ui/core/Tooltip'
import Tab from '@material-ui/core/Tab'
import Tabs from '@material-ui/core/Tabs'
import CircularProgress from '@material-ui/core/CircularProgress'
// @material-ui/icons
import Reply from '@material-ui/icons/Reply'
// core components
import GridContainer from 'components/Grid/GridContainer.jsx'
import GridItem from 'components/Grid/GridItem.jsx'
import Button from 'components/CustomButtons/Button.jsx'
import Media from 'components/Media/Media.jsx'
import { getDiscussionsByForumID } from 'util/APIUtils'
import profile4 from 'assets/img/faces/card-profile4-square.jpg'
import sectionPillsStyle from 'assets/jss/material-kit-pro-react/views/blogPostsSections/sectionPillsStyle.jsx'
class SectionPills extends React.Component {
constructor (props) {
super(props)
this.state = {
discussions: [],
isLoading: false,
active: 0,
forumID: 1
}
this.changeForum = this.changeForum.bind(this);
}
handleChange = (event, active) => {
this.setState({ active });
};
changeForum(fid) {
this.setState({ forumID: fid });
}
loadDiscussionList () {
let promise
promise = getDiscussionsByForumID(this.state.forumID)
if (!promise) {
return
}
this.setState({
isLoading: true
})
promise
.then(response => {
const discussions = this.state.discussions.slice()
this.setState({
discussions: discussions.concat(response),
isLoading: false
})
}).catch(error => {
this.setState({
isLoading: false
})
})
}
componentDidMount () {
this.loadDiscussionList()
}
shouldComponentUpdate (nextState) {
if (nextState.forumID != this.state.forumID) {
this.loadDiscussionList()
}
}
render () {
const { classes } = this.props
const flexContainerClasses = classNames({
[classes.flexContainer]: true,
[classes.horizontalDisplay]: false
})
const pillsClasses = classNames({
[classes.pills]: true,
[classes.horizontalPills]: false
})
const tabButtons = (
<Tabs
classes={{
root: classes.root,
fixed: classes.fixed,
flexContainer: flexContainerClasses,
indicator: classes.displayNone
}}
value={this.state.active}
onChange={this.handleChange}
centered={true}
>
<Tab
key={1}
label='YeePlus'
classes={{
root: pillsClasses,
labelContainer: classes.labelContainer,
label: classes.label,
selected: classes.primary
}}
onClick={() => this.changeForum(1)}
/>
<Tab
key={2}
label='Yeelight'
classes={{
root: pillsClasses,
labelContainer: classes.labelContainer,
label: classes.label,
selected: classes.primary
}}
onClick={() => this.changeForum(2)}
/>
<Tab
key={3}
label='Feedback'
classes={{
root: pillsClasses,
labelContainer: classes.labelContainer,
label: classes.label,
selected: classes.primary
}}
onClick={() => this.changeForum(3)}
/>
</Tabs>
)
const discussionList = []
this.state.discussions.forEach((discussion, discussionIndex) => {
discussionList.push(
<Media
key={discussion.id}
avatar={profile4}
title={
<span>
{discussion.title} <small>· 7 minutes ago</small>
</span>
}
body={
<p className={classes.color555}>
{discussion.title}
</p>
}
footer={
<div>
<Tooltip
id='tooltip-tina'
title='Reply to discussion'
placement='top'
classes={{ tooltip: classes.tooltip }}
>
<Button
color='primary'
simple
className={classes.footerButtons}
>
<Reply className={classes.footerIcons} /> Reply
</Button>
</Tooltip>
</div>
}
/>)
})
const ColorCircularProgress = withStyles({
root: {
color: '#9c27b0'
}
})(CircularProgress)
return (
<div className={classes.section}>
<GridContainer justify='center'>
<GridItem xs={12} sm={10} md={8}>
{tabButtons}
<div className={classes.tabSpace} />
{discussionList}
<div className={classes.textCenter} >
{
this.state.isLoading
? <ColorCircularProgress /> : null
}
</div>
</GridItem>
</GridContainer>
</div>
)
}
}
export default withStyles(sectionPillsStyle)(SectionPills)
错误信息:
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
50 | return
51 | }
52 |
> 53 | this.setState({
| ^ 54 | isLoading: true
55 | })
56 |
我想保留state isLoading,但我找不到同时保留它们的解决方案。
【问题讨论】:
-
“如何在 shouldComponentUpdate 中使用 setState” - 不要在
shouldComponentUpdate中设置状态 -
您需要重新考虑如何完全处理这种情况
-
考虑改用
getDerivedStateFromProps? -
您可能想改用“componentDidUpdate”
标签: javascript reactjs react-state react-lifecycle