DEV Community

Gonzalo
Gonzalo

Posted on

Como iniciar zustand de un server page al client en NextJs

En este post vamos a ver como podemos setear un store de zustand en un server page de NextJs y utilizarlo luego en cliente.

¿Por que querriamos hacer eso?

Pueden existir varios motivos, pero el principal es que supongamos que necesitamos setear el store con unos valores que recivimos de un terecero, como una llamada a una api.
Lo bueno de los server page es que podemos solicitar datos de forma asyncrona, pero si seteamos el store en un server page el store no existira en el cliente.

Creamos el store

Doy por echo en este post que sabes como instalar zustand y tienes conocimientos de nextjs.

store.ts

import {create} from 'zustand';

interface Store {
  todos: Todo[];
  addTodo: (text: string) => void;
  toggleTodo: (id: number) => void;
}

export const useTodoStore = create<Store>((set) => ({
  todos: [],
  addTodo: (text) => set((state) => ({
    todos: [...state.todos, { id: Date.now(), text, completed: false }]
  })),
  toggleTodo: (id) => set((state) => ({
    todos: state.todos.map(todo => 
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    )
  }))
}));
Enter fullscreen mode Exit fullscreen mode

Iniciamos store en server page

Ahora en nuestro server page recuperamos los todos iniciales que queremos setear y hacemos un setState:

 import useTodoStore from './store';

 export default async function Page() {
   const response = await fetch('https://jsonplaceholder.typicode.com/todos');
   if (!response.ok)
   throw new Error('Network response was not ok');

   useTodoStore.setState({
    todos: response.json()
   })
  }
Enter fullscreen mode Exit fullscreen mode

Sincronizar cliente con los datos que tenemos en el servidor

Ahora para este paso necesitamos crear un componenten de tipo cliente el cual vamos a usar para inicializar el store y poder usarlo en el lado de el cliente.

StoreInitializer

'use client';

import {useRef} from "react";

import useTodoStore from "./store";

export default function StoreInitializer({todos}: {
    todos: Todo[]
}) {
    const initialized = useRef(false);
    const store = useReservaStore();

    if (!initialized.current) {
        store.setState({ todos });
        initialized.current = true;
    }
    return null;
}
Enter fullscreen mode Exit fullscreen mode

En este punto ya tenemos los datos en el store y accesibles en el cliente y nos aseguramos de que cuando lo usemos en nuestra pagina cliente los datos ya este.

 import useTodoStore from './store';

 export default async function Page() {
   const response = await fetch('https://jsonplaceholder.typicode.com/todos');
   if (!response.ok)
   throw new Error('Network response was not ok');

   useTodoStore.setState({
    todos: response.json()
   })
  }

  return (
   <>
    <StoreInitializer todos={useTodoStore.getState().todos} />
    <Todos />
   </>
  )
Enter fullscreen mode Exit fullscreen mode

Links:

Top comments (0)