简体   繁体   中英

What are the best practices to initialize a Next.js webapp with data from an API and adding it to the state?

I'm using Zustand for state management (although I'd imagine the same principle applies to all state management libraries such as Redux or Recoil). I've thought about and tried:

  1. Fetching data using getStaticProps() and using useEffect() to push the data to state during the first page render. The problem is that the data isn't pushed to state until that specific page is loaded. I don't want to use getInitialProps() , as it's being deprecated.
  2. A solution that worked (sort of, not sure it's best practice though) was using SWR on _app.js to fetch the API data when the app first initializes, and pushing the data to state with useEffect() . This way I could freely populate the pages by using the data from state, and it only required one API call. Example below:
function MyApp({ Component, pageProps }) {
  
  // Load data from api with SWR
  const fetcher = (url) => fetch(url).then((res) => res.json());
  const { data, error } = useSWR(
    "https://example.com/api",
    fetcher
  );

  // Get data setter from state
  const setData = useStore((state) => state.setData);

  // When data is fetched successfully, populate state with data
  useEffect(() => {
    if (data) {
      setData(data);
    }
  }, [data]);

  if (error) return "Error has occured";
  if (!data) return "Loading...";

  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

export default MyApp;

Are there better ways to fetch data and use it to populate state on the first time the app is loaded? What are the best practices?

I got it working the right way using Zustand context provider and initializing it using Nextjs pageProps and getStaticProps() .

_app.js

function MyApp({ Component, pageProps }) {
  const createStore = initStore(pageProps.initZustand);
  return (
    <Provider createStore={createStore}>
      <Component {...pageProps} />
    </Provider>
  );
}

export default MyApp;

store.js

export const { Provider, useStore } = createContext();

let store = {
  names: ["Name 1", "Name 2", "Name 3"],
  random: [],
  setRandom: (data) => {
    set((state) => ({ random: data }));
  },
};

export const initStore = (data) => {
  const createStore = () =>
    create(
      devtools((set, get) => ({
        ...store,
        ...data,
      }))
    );

  return createStore;
};

index.js getStaticProps:

export async function getStaticProps(context) {
  const res = await fetch("https://jsonplaceholder.typicode.com/users");
  const posts = await res.json();

  return {
    props: {
      initZustand: {
        posts: posts,
      },
    },
  };
}

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