使用React 16.8,我已经用useReucer、useContext钩子实现了我的项目,并创建了一个类似于Redux的全局状态管理系统。
在视图中,当我试图在useEffect中获取数据时,它会导致最大更新深度错误。
我已经尝试了Facebook React-Hooks常见问题解答中的所有示例,但无法解决问题。
我的package.json是这样的:
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-app-polyfill": "^1.0.1",
"react-chartjs-2": "^2.7.6",
"react-dom": "^16.8.6",
"react-router-config": "^5.0.0",
"react-router-dom": "^5.0.0",
"react-test-renderer": "^16.8.6",
"react-uuid": "^1.0.2",
"reactstrap": "^7.1.0",
"simple-line-icons": "^2.4.1",
"styled-components": "^4.2.0"
下面是我的代码示例:
这里是风景。js
import React, { useEffect, useRef } from 'react'
import useView from '/store/hooks/useView'
import isEqual from '/services/isEqual'
import loading from '/service/loading'
const View = () => {
const viewContext = useView()
let viewContextRef = useRef(viewContext)
// Keep latest viewContext in a ref
useEffect(() => {
viewContextRef.current = viewContext
})
useEffect(() => {
// Fetch Data
async function fetchData() {
// This causes the loop
viewContextRef.current.startFetchProcess()
const url = 'html" target="_blank">http://example.com/fetch/data/'
try {
const config = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
}
}
const response = await fetch(url, config)
if (response.ok) {
const res = await response.json()
finalizeGetViewList(res)
// This causes the loop
viewContextRef.current.stopFetchProcess()
return res
}
} catch (error) {
console.log(error)
return error
}
}
// Prepare data for rows and update state
const finalizeGetViewList = (data) => {
const { Result } = data
if (Result !== null) {
let Arr = []
for (let i = 0; i < Result.length; i++) {
let Obj = {}
//...
//...
Arr.push(Obj)
}
// I compare the prevState with the fetch data to reduce
// the number of update state and re-render,
// so this section do not cause the problem
if (!isEqual(roleContextRef.current.state.rows, Arr)) {
viewContextRef.current.storeViewList(Arr)
}
} else {
console.log(errorMessage)
}
}
function doStartFetch () {
fetchData()
}
const startingFetch = setInterval(doStartFetch, 500)
// aborting request when cleaning
return () => {
clearInterval(startingFetch)
}
}, [])
const {
rows,
isLoading
} = viewContext.state
if (isLoading) {
return (loading())
} else {
return (
<div>
{rows.map(el => (
<tr key={el.id}>
<td>el.name</td>
<td>el.price</td>
<td>el.discount</td>
</tr>
))}
</div>
)
}
}
export default View
如果你真的愿意解决这个问题,请看看其他文件的存储周期。
这是useView的钩子。js:
import { useContext } from 'react'
import { StoreContext } from "../providers/Store"
export default function useUsers() {
const { state, actions, dispatch } = useContext(StoreContext)
const startFetchProcess = () => {
dispatch(actions.viewSystem.startFetchProcess({
isLoading: true
}))
}
const storeViewList = (arr) => {
dispatch(actions.viewSystem.storeViewList({
rows: arr
}))
}
const stopFetchProcess = () => {
dispatch(actions.viewSystem.stopFetchProcess({
isLoading: false
}))
}
return {
state: state.viewSystem,
startFetchProcess,
storeViewList,
stopFetchProcess,
}
}
这是viewReducer。js发送:
const types = {
START_LOADING: 'START_LOADING',
STORE_VIEW_LIST: 'STORE_VIEW_LIST',
STOP_LOADING: 'STOP_LOADING',
}
export const initialState = {
isLoading: false,
rows: [
{
ProfilePicture: 'Avatar',
id: 'id', Name: 'Name', Price: 'Price', Discount: 'Discount'
}
],
}
export const actions = {
storeViewList: (data) => ({ type: types.STORE_VIEW_LIST, value: data }),
startFetchProcess: (loading) => ({ type: types.START_LOADING, value: loading }),
stopFetchProcess: (stopLoading) => ({ type: types.STOP_LOADING, value: stopLoading })
}
export const reducer = (state, action) => {
switch (action.type) {
case types.START_LOADING:
const Loading = { ...state, ...action.value }
return Loading
case types.STORE_VIEW_LIST:
const List = { ...state, ...action.value }
return List
case types.STOP_LOADING:
const stopLoading = { ...state, ...action.value }
return stopLoading
default:
return state;
}
}
export const register = (globalState, globalActions) => {
globalState.viewSystem = initialState;
globalActions.viewSystem = actions;
}
这是StoreProvider提供应用程序中的每个组件并传递状态:
import React, { useReducer } from "react"
import { reducer, initialState, actions } from '../reducers'
export const StoreContext = React.createContext()
export const StoreProvider = props => {
const [state, dispatch] = useReducer(reducer, initialState)
return (
<StoreContext.Provider value={{ state, actions, dispatch }}>
{props.children}
</StoreContext.Provider>
)
}
这是还原剂指数。js为不同视图克隆多个还原器:
import { user as userData, reducer as loginReducer } from './loginReducer'
import { register as viewRegister, reducer as viewReducer } from './viewReducer'
import { register as groupRegister, reducer as groupsReducer } from './groupsReducer'
export const initialState = {};
export const actions = {};
userData(initialState, actions)
viewRegister(initialState, actions)
groupRegister(initialState, actions)
export const reducer = (state, action) => {
return {
credentials: loginReducer(state.credentials, action),
roleSystem: viewReducer(state.viewSystem, action),
groups: groupsReducer(state.groups, action)
}
}
很抱歉有很多文件,但是没有其他方法来解释这种情况。曾经使用Redux的人可以理解这种方法。国家没有问题=
经典的let didCancel=false
方法不起作用。如果我将状态与新获取的数据进行比较,问题就解决了。但是当我添加加载时,它会触发useReducer并重新呈现页面,这会导致无限循环。
UseRef和clearInterval不会阻止它,出现以下错误:
Invariant Violation: 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.
我会尝试分散您的关注点,在初始渲染时调度startFetchProcess
操作,然后在加载状态更新时提取:
useEffect(() => {
viewContextRef.current.startFetchProcess()
}, [])
useEffect(() => {
// Fetch Data
async function fetchData () {
// This causes the loop
// moved to the dependency array
const url = 'http://example.com/fetch/data/'
// ..... //
function doStartFetch () {
roleContext.state.isLoading && fetchData()
}
const startingFetch = setInterval(doStartFetch, 500)
// aborting request when cleaning
return () => {
clearInterval(startingFetch)
}
}, [roleContext.state.isLoading])
问题内容: 我试图在ReactJS中切换组件的状态,但出现错误: 超过最大更新深度。当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时,可能会发生这种情况。React限制了嵌套更新的数量,以防止无限循环。 我在代码中看不到无限循环,有人可以帮忙吗? ReactJS组件代码: 问题答案: 那是因为您在render方法中调用了toggle
我在代码中没有看到无限循环,有人能帮忙吗? ReactJS组件代码:
当我运行我的代码时,我收到了这个错误。 错误:超过了最大更新深度。当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时,会发生这种情况。React限制嵌套更新的数量,以防止无限循环。这是我的代码 我是用react native编写代码的初学者。我只想得到first_name_user的值,但当我通过this.state调用这个值时。fi
我正在用React做我的前几个实验,在这个组件中,我调用了一个外部API来获取所有NBA玩家的列表,通过作为组件道具接收的teamId过滤它们,最后呈现过滤玩家的标记。 一个需要考虑的问题是,由于我调用了API并获得了一个大列表,所以我将它保持在组件的状态,以便对该组件的新调用将使用该状态,而不是再次调用API。这不是生产代码,我没有API,所以我这样做是因为我收到了“太多请求”消息,因为我一直在
我在React中运行我的应用程序时收到一个错误。这个错误有很多问题,但我不知道如何解决它。当我按下链接时,它会指向登录组件。“http://localhost:3000/login” 这是我在网站上得到的错误: “已超出最大更新深度。当组件重复调用组件内部的 setState 时,可能会发生这种情况“组件将更新”或“组件更新”。React 限制了嵌套更新的数量,以防止无限循环。 这是我的登录页面:
我目前收到Maxiumum更新深度错误,不知道为什么。在我的代码中看不到无限循环。 "超过了最大更新深度。当组件在useEffect内部调用setState时,可能会发生这种情况,但useEffect要么没有依赖关系数组,要么其中一个依赖关系在每次渲染时都会发生变化。 此处显示错误 ReactJS组件代码: 下面的代码似乎有错误:超过了最大更新深度。当组件在useEffect中调用setState