简体   繁体   中英

Fetch global data for the whole app in Next.js on initial page load

In my Next.js application I have search filters. Filters consist of checkboxes, and to render these checkboxes I need to fetch (GET) all possible options from the API.

Those filters are available on many pages, so regardless the page where user lands I need to fetch the data for filters immediately and put it in the local storage to avoid further excessive API calls. Putting API call in each page is not an option.

I see the one option is to put the API call in getInitialProps in _app.js , but then according to Next.js docs automatic static optimization will not work and every page in my app will be server-side rendered.

So what is the proper way to fetch such global data in Next.js?

--------UPDATE

So at this moment I've used the next solution: in _app.js I put useEffect React Hook and once the Frontend is ready I am checking whether my data for whole application is in locale storage. If it's not then fetch data from server and put in local storage for further use.

// _app.js
const AppWrapper = ({ children }) => {
    const dispatch = useAppDispatch();

    useEffect(() => {
        dispatch({ type: FRONTEND_LOADED });
        loadInitialData(dispatch);
    }, [false]);

    return <>{children}</>;
};

class MyApp extends App {
    render() {
        const { Component, router, pageProps } = this.props;

        return (
            <>
                <AppProvider>
                    <AppWrapper>
                        <MainLayout pathname={router.pathname}>
                            <Component {...pageProps} />
                        </MainLayout>
                    </AppWrapper>
                </AppProvider>
            </>
        );
    }
}
// loadInitialData.js
import {
    SET_DIETS_LIST,
    UPDATE_FILTERS_FROM_CACHE,
} from "Store/types";
import fetch from "isomorphic-unfetch";

export default dispatch => {
    const ls = JSON.parse(localStorage.getItem("filters"));
    if (ls) {
        const localStorageState = {
            diet: {
                list: ls.diet.list || [],
                selected: ls.diet.selected || [],
            },
            ...
        };
        dispatch({
            type: UPDATE_FILTERS_FROM_CACHE,
            payload: { filters: localStorageState },
        });
    }

    if (!ls || !ls.diet.list.length) {
        fetch(`${process.env.API_URL}/diets`)
            .then(r => r.json())
            .then(data => {
                dispatch({ type: SET_DIETS_LIST, payload: { data[0] } });
            });
    }
...
};

You could do it with Context API also.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM