React/TypeScript `Error: Maximum update depth exceeded.` when trying to redirect on timeout
React/TypeScript `Error: Maximum update depth exceeded.` when trying to redirect on timeout
我有一个项目正在尝试动态地从第 1 页重定向到第 2 页等。这以前对我有用,但最近我收到此错误:
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.
今天早上看到此消息后,多个 SO 页面都说不要在 render
中调用 setState
,我已将 setTimeout
调用移至 componentDidMount
。
到目前为止我已经试过了
- 调用一个改变 this.props.pageWillChange
属性 的函数,然后在渲染 I return 一个基于该条件的对象
- return在渲染中的内联 if 语句中设置对象挂起条件
- 将 pageWillChange 变成本地道具,而不是 class 继承的道具(我非常喜欢这个选项,因为这个组件的每个新版本的状态都是相同的)
还有很多东西,但这些感觉都行得通。有人能帮忙吗?
import React, { Component } from "react"
import axios from "axios"
import { GridList, GridListTile } from "@material-ui/core"
import "../assets/scss/tile.scss"
import Request from "../config.json"
import DataTile from "./DiagnosticDataTile"
import { IDiagnosticResultData } from "../interfaces/IDiagnosticResultData"
import { Redirect } from "react-router"
interface IProps {
category: string
redirect: string
}
interface IPageState {
result: IDiagnosticResultData[]
pageWillChange: boolean
}
class Dashboard extends Component<IProps, IPageState> {
_isMounted = false
changeTimeInMinutes = 0.25
willRedirect: NodeJS.Timeout
constructor(props: Readonly<IProps>, state: IPageState) {
super(props)
this.state = state
console.log(window.location)
}
componentDidMount(): void {
this._isMounted = true
this.ChangePageAfter(this.changeTimeInMinutes)
axios
.get(Request.url)
.then(response => {
if (this._isMounted) {
this.setState({ result: response.data })
}
})
.catch(error => {
console.log(error)
})
}
componentWillUnmount(): void {
this._isMounted = false
clearTimeout(this.willRedirect)
}
ChangePageAfter(minutes: number): void {
setTimeout(() => {
this.setState({ pageWillChange: true })
}, minutes * 60000)
}
render() {
var data = this.state.result
//this waits for the state to be loaded
if (!data) {
return null
}
data = data.filter(x => x.categories.includes(this.props.category))
return (
<GridList
cols={this.NoOfColumns(data)}
cellHeight={this.GetCellHeight(data)}
className="tileList"
>
{this.state.pageWillChange ? <Redirect to={this.props.redirect} /> : null}
{data.map((tileObj, i) => (
<GridListTile
key={i}
className="tile"
>
<DataTile data={tileObj} />
</GridListTile>
))}
</GridList>
)
}
}
export default Dashboard
(React 和 TypeScript 非常新,我的第一个 SO post 哇!)
试试下面的代码,还有几点:
- 不需要
_isMounted
字段。 'componentDidMount' 中的代码始终在挂载后运行。
- 无需在构造函数中设置状态。实际上不再需要构造函数了。
- 我在
componentWillUnmount
坐骑中看不到 clearTimeout
的太多意义。它永远不会超时。
关于路由。您可以使用 'withRouter' 高阶函数在 changePageAfter
方法中以编程方式更改路由。
希望对您有所帮助!
import axios from "axios"
import { GridList, GridListTile } from "@material-ui/core"
import "../assets/scss/tile.scss"
import Request from "../config.json"
import DataTile from "./DiagnosticDataTile"
import { IDiagnosticResultData } from "../interfaces/IDiagnosticResultData"
import { Redirect, RouteComponentProp } from "react-router"
interface PropsPassed {
category: string
redirect: string
}
type Props = PropsPassed & RouteComponentProp
interface IPageState {
result: IDiagnosticResultData[]
pageWillChange: boolean
}
class Dashboard extends Component<Props, IPageState> {
changeTimeInMinutes = 0.25
willRedirect: NodeJS.Timeout
componentDidMount(): void {
this.ChangePageAfter(this.changeTimeInMinutes)
axios
.get(Request.url)
.then(response => {
this.setState({ result: response.data })
})
.catch(error => {
console.log(error)
})
}
changePageAfter(minutes: number): void {
setTimeout(() => {
this.props.history.push({
pathname: '/somepage',
});
}, minutes * 60000)
}
render() {
var data = this.state.result
//this waits for the state to be loaded
if (!data) {
return null
}
data = data.filter(x => x.categories.includes(this.props.category))
return (
<GridList
cols={this.NoOfColumns(data)}
cellHeight={this.GetCellHeight(data)}
className="tileList"
>
{data.map((tileObj, i) => (
<GridListTile
key={i}
className="tile"
>
<DataTile data={tileObj} />
</GridListTile>
))}
</GridList>
)
}
}
export default withRouter(Dashboard)
我有一个项目正在尝试动态地从第 1 页重定向到第 2 页等。这以前对我有用,但最近我收到此错误:
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.
今天早上看到此消息后,多个 SO 页面都说不要在 render
中调用 setState
,我已将 setTimeout
调用移至 componentDidMount
。
到目前为止我已经试过了
- 调用一个改变 this.props.pageWillChange
属性 的函数,然后在渲染 I return 一个基于该条件的对象
- return在渲染中的内联 if 语句中设置对象挂起条件
- 将 pageWillChange 变成本地道具,而不是 class 继承的道具(我非常喜欢这个选项,因为这个组件的每个新版本的状态都是相同的)
还有很多东西,但这些感觉都行得通。有人能帮忙吗?
import React, { Component } from "react"
import axios from "axios"
import { GridList, GridListTile } from "@material-ui/core"
import "../assets/scss/tile.scss"
import Request from "../config.json"
import DataTile from "./DiagnosticDataTile"
import { IDiagnosticResultData } from "../interfaces/IDiagnosticResultData"
import { Redirect } from "react-router"
interface IProps {
category: string
redirect: string
}
interface IPageState {
result: IDiagnosticResultData[]
pageWillChange: boolean
}
class Dashboard extends Component<IProps, IPageState> {
_isMounted = false
changeTimeInMinutes = 0.25
willRedirect: NodeJS.Timeout
constructor(props: Readonly<IProps>, state: IPageState) {
super(props)
this.state = state
console.log(window.location)
}
componentDidMount(): void {
this._isMounted = true
this.ChangePageAfter(this.changeTimeInMinutes)
axios
.get(Request.url)
.then(response => {
if (this._isMounted) {
this.setState({ result: response.data })
}
})
.catch(error => {
console.log(error)
})
}
componentWillUnmount(): void {
this._isMounted = false
clearTimeout(this.willRedirect)
}
ChangePageAfter(minutes: number): void {
setTimeout(() => {
this.setState({ pageWillChange: true })
}, minutes * 60000)
}
render() {
var data = this.state.result
//this waits for the state to be loaded
if (!data) {
return null
}
data = data.filter(x => x.categories.includes(this.props.category))
return (
<GridList
cols={this.NoOfColumns(data)}
cellHeight={this.GetCellHeight(data)}
className="tileList"
>
{this.state.pageWillChange ? <Redirect to={this.props.redirect} /> : null}
{data.map((tileObj, i) => (
<GridListTile
key={i}
className="tile"
>
<DataTile data={tileObj} />
</GridListTile>
))}
</GridList>
)
}
}
export default Dashboard
(React 和 TypeScript 非常新,我的第一个 SO post 哇!)
试试下面的代码,还有几点:
- 不需要
_isMounted
字段。 'componentDidMount' 中的代码始终在挂载后运行。 - 无需在构造函数中设置状态。实际上不再需要构造函数了。
- 我在
componentWillUnmount
坐骑中看不到clearTimeout
的太多意义。它永远不会超时。
关于路由。您可以使用 'withRouter' 高阶函数在 changePageAfter
方法中以编程方式更改路由。
希望对您有所帮助!
import axios from "axios"
import { GridList, GridListTile } from "@material-ui/core"
import "../assets/scss/tile.scss"
import Request from "../config.json"
import DataTile from "./DiagnosticDataTile"
import { IDiagnosticResultData } from "../interfaces/IDiagnosticResultData"
import { Redirect, RouteComponentProp } from "react-router"
interface PropsPassed {
category: string
redirect: string
}
type Props = PropsPassed & RouteComponentProp
interface IPageState {
result: IDiagnosticResultData[]
pageWillChange: boolean
}
class Dashboard extends Component<Props, IPageState> {
changeTimeInMinutes = 0.25
willRedirect: NodeJS.Timeout
componentDidMount(): void {
this.ChangePageAfter(this.changeTimeInMinutes)
axios
.get(Request.url)
.then(response => {
this.setState({ result: response.data })
})
.catch(error => {
console.log(error)
})
}
changePageAfter(minutes: number): void {
setTimeout(() => {
this.props.history.push({
pathname: '/somepage',
});
}, minutes * 60000)
}
render() {
var data = this.state.result
//this waits for the state to be loaded
if (!data) {
return null
}
data = data.filter(x => x.categories.includes(this.props.category))
return (
<GridList
cols={this.NoOfColumns(data)}
cellHeight={this.GetCellHeight(data)}
className="tileList"
>
{data.map((tileObj, i) => (
<GridListTile
key={i}
className="tile"
>
<DataTile data={tileObj} />
</GridListTile>
))}
</GridList>
)
}
}
export default withRouter(Dashboard)