TamTam
TamTam

Reputation: 567

Error: Maximum update depth exceeded when using react-hooks

I'm trying to change all of my source code from using react with redux to react-hook with redux and connect It with firebase:

This warning occured when I redirect to 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)

in 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');
);

in 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>
    );
}

In 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;

in 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());
};

in BlogReducer.js:

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

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

in 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;

I understand what the warning is trying to say, but not much experience with react hook.

Upvotes: 2

Views: 822

Answers (1)

Josh Pittman
Josh Pittman

Reputation: 7324

None of the code you have presented shows where you are using your firestore data and setting it to state. Use setState to actually store the data in your react app.

Upvotes: 2

Related Questions