Provider component's useEffect is running before mounted

Viewed 1628

I have a Provider component which passes down some data through its props, which will later be used across the app.

It looks something like this:

export const MyContext = createContext({});
MyContext.displayName = 'My Context';


export const MyProvider = ({ children }) => {
    const [items, setItems] = useState([]);
    const [loading, setLoading] = useState(false);

    const setData = async () => {
        setLoading(true);
        setItems(await getItemsApiCall());
        setLoading(false);
    };

    useEffect(() => {
        console.warn('component re-rendering')
        if (!items.length) {
            setData();
        }
    }, [items]);

    return (
        <MyContext.Provider value={{items, loading}}>
            {children}
        </MyContext.Provider>
    );
};

In theory this should work fine, however I am seeing a bunch of extra re-renders through the console.warn which seem unnecessary, also I am getting the warning relating to the state update on an unmounted component

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application...

Although I have seen the solution for this in other threads, none of them work for me because I am not only setting items, but also loading, which I need to put in spinners and other such things on other parts of the app while fetching data.

Anyway, is there a way to prevent these re-render before the mount and to surpress the warning under these circumstances?

Edit: For the record, I am currently getting 2 re-renders before the warning relating to updating the state of an unmounted component, and then two other re-renders (those of which are to be expected). So basically, my console look something like this:

component re-rendering

component re-rendering

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application...

component re-rendering

component re-rendering

Edit2: For what it is worth, I would also like to show how the MyProvider is being used. It is simply wrapping another component in a particular route. Something like this:

const App = () => (
    <Router>
        <Switch>
            <Route
            path='/items'
            exact
            component={() => (
                <MyProvider>
                    <Items/>
                </MyProvider>
            )}
            />
        </Switch>
    </Router>
)

The behaviour I get above happens simply when visiting the /items route.

0 Answers
Related