Jake Wheeler

Using Zustand With TypeScript

August 15, 2020

I love working with Zustand when I need client-side state management in my React applications. However, one of the things I struggled with recently was using it with TypeScript. I decided to write this short post to help anyone else that might run into a similar problem.

My need in this case was simple: I wanted to be able to fetch some data from an API one time when my application started up and then make that data available everywhere in my application.

Here is what my typed Zustand store looks like:

// utils/store.ts

import create from "zustand"
import { FeedItemProps } from "../types"
import { fetchInitialFeedContent } from "./helpers" // returns data from the API using axios

interface Set {
  json: FeedItemProps[] // this property will hold my data
  fetch: (url: string) => void // this function will store the fetched data in the json property
}

export const [useStore, api] = create<Set>(
  (set): Set => ({
    json: [],
    fetch: async (url: string) => {
      try {
        const response = await fetchInitialFeedContent()
        set({ json: response })
      } catch (err) {
        console.error("Couldn not fetch initial data")
        set({ json: [] })
      }
    },
  })
)

Using the Set interface in the right spots here is key. While this is not too bad at all, most of my trouble came from struggling to find examples of how to type the store correctly.

For the sake of completion, here's an example using the store:

// pages/_app.tsx

import { AppProps } from 'next/app';
import { useStore } from '../utils/stores';
import { useState, useEffect } from 'react';

export default function App({ Component, pageProps }: AppProps) {
  const { json, fetch } = useStore();
  const [isFetched, setIsFetched] = useState(false);

  // initial feed data fetch
  useEffect(() => {
    if (!isFetched) {
      fetch(TIMELINE_KEY);
      setIsFetched(true);
    }
  }, [setIsFetched, json]);

...

}

I'm calling the fetch function once at the start of my application and then using json from the store in many other spots of the app.

I hope this helps you!

Jake