Identifying the Problem

Steven Wexler - Oct 26 - - Dev Community

Identify the Problem

The first step to building anything is identifying a problem to target. I noticed a lot of devs were asking for guidance on integrating async queries into Zustand on reddit, github, and Stackoverflow. And I felt this exact pain myself. This is a real problem.

Investigate the Solutions

On the forums I was seeing solutions. They generally fell into two buckets - use fetch in an async function or use Tanstack Query. Time to investigate the solutions.

1) Use fetch in an async function

This solution works well out of the box and is simple. But it isn't feature-rich. Without caching, retries, data invalidation, etc. devs will quickly run into bad UX for their site. So this solution didn't cut it. I can do better.

const useStore = create((set) => ({
  currentUser: '1', // Default user ID
  setCurrentUser: (userId) => set({ currentUser: userId }),
  data: null,
  loading: false,
  error: null,

  // Action to fetch data
  fetchData: async (userId) => {
    set({ loading: true, error: null });
    try {
      const response = await fetch(`https://api.example.com/users/${userId}`).then(r.json());
      if (!response.ok) {
        throw new Error(`Error: ${response.status}`);
      }
      const data = await response.json();
      set({ data, loading: false });
    } catch (error) {
      set({ error: error.message, loading: false });
    }
  },
}));

// Example usage in a React component
function Component() {
  const { data, loading, error, fetchData } = useStore();

  useEffect(() => {
    fetchData('https://api.example.com/data');
  }, [fetchData]);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;

  return (
    <div>
      <h1>Data</h1>
    <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

2) Use Tanstack Query

Tanstack Query is a fantastic library. It's feature-rich. It's well-documented. But it's also complex and works very differently from Zustand. Dev's can use Zustand + Tanstack to build a great app. But I thought I can build a simpler solution if I integrate an async data handling library directly into Zustand. This is a strong solution. But Still I can do better.

// Create a Zustand store to manage the current user state
const useStore = create((set) => ({
  currentUser: '1', // Default user ID
  setCurrentUser: (userId) => set({ currentUser: userId }),
}));

function useFetchUserInfo(userId) {
  return useQuery(
    ['userInfo', userId],
    async () => await fetch(`https://api.example.com/users/${userId}`).then(r.json())
  );
}

function Component() {
  const { currentUser, setCurrentUser } = useStore();
  const { data: userInfo, error, isLoading } = useFetchUserInfo(currentUser);

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <div>
      <h1>User Information</h1>
      <span>{userInfo.name}</span>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Set MVP Goals

Now I've looked at the problem. I've looked at the solution. I believe I can build a better solution. Time to set goals to get something built quickly. My goal is simple - build an async data handling library for Zustand that works well for basic usage, has a path to become feature-rich, and is simple to integrate. And build it quickly.

Plan

At this point it's temping to create a well though-out plan. Building an async library is a big task. And without a good plan I'll probably build messy solution. But the truth is I don't have enough information to plan effectively yet. I am going to learn a lot as I build. It's important that I stay flexible and adapt to new information. When I have more information I'll plan more effectively.

Build

The fun part! Now it's time to build. Just start coding with my goal in mind. Be open to new ideas as they come in. And put a timebox on it - I chose 1 month. Remember, the goal is to build a first version quickly. Then I can get more information through feedback quickly.

. . .