错误:使用 react-hooks 时超出最大更新深度

Posted

技术标签:

【中文标题】错误:使用 react-hooks 时超出最大更新深度【英文标题】:Error: Maximum update depth exceeded when using react-hooks 【发布时间】:2020-03-26 16:05:35 【问题描述】:

我正在尝试将我的所有源代码从使用 react with redux 更改为 react-hook with redux 并将其与 firebase 连接:

当我重定向到 localhost:3000/blogs 时出现此警告,

index.js:1375 Warning: Maximum update depth exceeded. This can happen when a 
component calls 
setState inside useEffect, but useEffect either doesn't have a dependency 
array, or one of the 
dependencies changes on every render.
in BlogDashboard (created by Context.Consumer)
in Route (at App.jsx:32)
in Switch (at App.jsx:31)
in div (created by Container)
in Container (at App.jsx:30)
in Route (at App.jsx:27)
in App (at src/index.js:44)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:40)
in ReduxFirestoreProvider (created by ReactReduxFirebaseProvider)
in ReactReduxFirebaseProvider (at src/index.js:39)
in Provider (at src/index.js:38)

在 Index.js 中:

ReactDOM.render(
    <Provider store=store>
         <ReactReduxFirebaseProvider ...rrfProps> // firebase worked fine
             <BrowserRouter>
                    <ReduxToastr timeOut=2000 preventDuplicates position="bottom-right" 
                                transitionIn="fadeIn" transitionOut="fadeOut" />
                    <App />
             </BrowserRouter>
         </ReactReduxFirebaseProvider>
     </Provider>, 
     document.getElementById('root');
);

在 App.jsx 中:

const App = () => 
const auth = useSelector(state => state.firebase.auth, []);
if(!auth.isLoaded && auth.isEmpty) return <LoadingComponent />

return (
    <Fragment>
        <ModalManager />
        <Switch>
            <Route exact path='/' component=HomePage/>
        </Switch>
        <Route path='/(.+)' render=() => (
            <Fragment>
                <NavBar />
                <Container className="main">
                    <Switch>
                        <Route exact path='/blogs' component=BlogDashboard />
                        <Route path='/blogs/:id' component=BlogDetailedPage />
                    </Switch>
                </Container>
            </Fragment>
            ) 
        />
    </Fragment>
    );

在 BlogDashboard.jsx 中:

const BlogDashboard = () => 
const dispatch = useDispatch();
const firestore = useFirestore();

const blogs = useSelector(state => CastToArray(state.firestore.data.blogs) || []);//this worked fine
const moreBlogs = useSelector(state => state.blogs.moreBlogs);
const loading = useSelector(state => state.async.loading);

useEffect(() => 
    const getBlogs = async () => 
        await dispatch(getPagedBlogs(firestore));
    ;

    if(blogs.length === 0) 
        getBlogs();
     else 
    
, [dispatch, firestore, blogs]);

const handleGetNextBlogs = async () => 
    await dispatch(getPagedBlogs(firestore));
;


return (
    <Grid>
        <Grid.Column width=10>
            <BlogList blogs=blogs loading=loading moreBlogs =moreBlogs getNextBlogs= 
                                                                         handleGetNextBlogs /> 

        </Grid.Column>
        <Grid.Column width=10>
            <Loader active=loading />
        </Grid.Column>
    </Grid>
    ); 
;

export default BlogDashboard;

在 BlogActions 中:

export const getPagedBlogs = (firestore) => 
async (dispatch, getState) => 
    dispatch(StartAction());
    const LIMIT = 5;
    let nextBlog = null;

    const firestore: data: blogs: items = getState();

    if (items && Object.keys(items).length >= LIMIT) 
        let itemsArray = objectToArray(items);
        nextBlog = await firestore.collection('blogs').doc(itemsArray[itemsArray.length - 
         1].id).get();
    

    let query = await firestore.get(
        collection: 'blogs',
        limit: LIMIT,
        where: ['date', '<=', new Date()],
        startAfter: nextBlog,
        storeAs: 'blogs'
    );

    if(query.docs.length < LIMIT) 
        dispatch(type: MORE_BLOGS);
    
    dispatch(FinishAction());
;

在 BlogReducer.js 中:

const initialState =  
    blogs: [],
    moreBlogs: true,
;
export const moreBlogs = (state) => 
    return 
        ...state.blogs,
        moreBlogs: true
    


export default createReducer(initialState, 
    [MORE_BLOGS]: moreBlogs
);

在 BlogList.jsx 中:

const BlogList = (blogs, moreBlogs, getNextBlogs, loading) => 
<Fragment>
    blogs && blogs.length !== 0 && 
         //Load blogs, using 'react-scroll-infinite'.
        <InfiniteScroll pageStart=0 loadMore=getNextBlogs hasMore= 
  !loading && moreBlogs initialLoad=false> 
            blogs && blogs.map(blog => (
                <BlogListItem key=blog.id blog=blog />
            ))
        </InfiniteScroll>
    
</Fragment>

export default BlogList;

我明白警告的意思,但对 react hook 没有太多经验。

【问题讨论】:

好像你在渲染方法里面做 setState 。尝试在渲染之外使用 setState 你在哪里设置状态?您提供的代码都没有显示您在哪里使用 Firestore 数据并将其设置为状态。我假设这是在BlogList 内。请告诉我们您在哪里使用setState @JoshPittman,谢谢你提醒我,我更新了我的帖子。目前我没有在 react 中使用任何 setState 方法,我只是在 blogReducer 中创建了一个 intialState 并且 blogs 是一个空数组。 我使用“const blogs = useSelector(...)”从 Firestore 获取数据,在 BlogDashboard.jsx 中声明,博客列表运行良好 太棒了。请接受下面添加的答案,以帮助遇到类似问题的其他人。 【参考方案1】:

您提供的代码均未显示您在何处使用 Firestore 数据并将其设置为状态。使用 setState 将数据实际存储在您的 react 应用中。

【讨论】:

以上是关于错误:使用 react-hooks 时超出最大更新深度的主要内容,如果未能解决你的问题,请参考以下文章

小部件更新的 RemoteViews 超出最大位图内存使用错误

React Typescript with hooks:最大更新深度超出错误

Tkinter,错误最大递归深度超出

尝试在反应组件的返回中使用 setstate 更新状态并获得“最大更新深度超出错误”?

ReactJS - 超出最大更新深度错误

如何在“React(设置状态)”中解决“超出最大更新深度”