Search code examples
reactjsreact-contextpouchdb

Too many rerenders in useContext for pouchDb


import React, { useState, useMemo } from 'react';
import PouchDB from 'pouchdb-browser';
import findPlugin from 'pouchdb-find';

const PouchdbContext = React.createContext({
    availableScanners: [''],
    changeDb: () => {},
});

export function PouchdbContextProvider({ children }) {
  // const [localDb, setLocalDb] = useState();
  // const [remoteDb, setRemoteDb] = useState();
  const [id, setId] = useState();

  const baseUrl = 'http://*:*';
  const username = '********';
  const password = '****';

  PouchDB.plugin(findPlugin);

  setId(localStorage.getItem('cb-remoteDb'));
  // const localDb = new PouchDB(`localdb${id}`);
  const contextValue = useMemo(async () => {
    const changeDbHandler = (index) => {
      setId(index);
    };
    const localDb = await new PouchDB(`localdb${id}`);
    localDb.info();
    const remoteDb = new PouchDB(`${baseUrl}/remote${id}`, {
      auth: { username, password },
    });
    remoteDb.info();

    PouchDB.sync(localDb, remoteDb, { live: true, retry: true });

    return { localDb, changeDb: changeDbHandler };
  }, [id]);
  return (
    <PouchdbContext.Provider value={contextValue}>
      {children}
    </PouchdbContext.Provider>
  );
}
export default PouchdbContext;

I'm trying to create a Context Provider for pouchdb. I get an error saying to many rerenders. Error : Too many re-renders. React limits the number of renders to prevent an infinite loop.


Solution

  • You should put all of this logic inside of useEffect because this way prevents React from managing effects properly and breaks the Component during rendering, React has clarified it in two places, the first is in a GitHub gist in a document named The Rules I highly recommend you to read it will clarify a lot of things to you and will correct wrong thoughts, and the second one is in the new React docs...if you referred to it you'd see that React only lets you adjust the state during rendering but this is an exceptional state and any other side-effect should be in an effect handler (such like useEffect) to keep the component pure as much as possible.

    You made a serious mistake by making HTTP requests to some external system or synchronizing with some external system outside effect handler and actually, those cases should only exist inside of the effect handler, a matter of fact, React made useEffect exactly for them!

    so put them all in useEffect then tell me what happened!