フロントエンド開発の先端を突っ走るNext.js
next.js アプリの初期化( npx create-next-app@latest --use-npm <アプリ名> )

zustand

● zustandのインストール

npm i zustand

● zustand dev tools のインストール

とても便利なので、こちらから入れておきましょう

https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ja

● storeの作成

src/stores/book.ts

import { create } from "zustand";

type BookStoreData = {
  amount: number;
  title: string;
};

const initialData: BookStoreData = {
  amount: 0,
  title: "",
};

interface BookStore {
  book: BookStoreData;
  updateAmount: (newAmount: number) => void;
  updateTitle: (newTitle: string) => void;
  fetchTitle: () => void;
}

export const useBookStore = create<BookStore>((set, get) => ({
  book: { ...initialData },

  updateAmount: (newAmount: number) => {
    const amountState = get().book.amount;
    const newBook: BookStoreData = {
      amount: newAmount + amountState,
      title: get().book.title,
    };
    set({ book: newBook });
  },

  updateTitle: (newTitle: string) => {
    const titleState = get().book.title;
    const newBook: BookStoreData = {
      amount: get().book.amount,
      title: newTitle,
    };
    set({ book: newBook });
  },

  fetchTitle: async () => {
    await new Promise((resolve) => setTimeout(resolve, 2000));
    const newBook: BookStoreData = {
      amount: get().book.amount,
      title: "fetched Title",
    };
    set({ book: newBook });
  },
}));

● コンポーネントで使用する

ストア値の参照 :  const book = useBookStore((state) => state.book);
アクションfetchTitle の呼び出し : const fetchTitle = useBookStore((state) => state.fetchTitle);

const BookSample = () => {
  const book = useBookStore((state) => state.book);
  const updateAmount = useBookStore((state) => state.updateAmount);
  const updateTitle = useBookStore((state) => state.updateTitle);
  const fetchTitle = useBookStore((state) => state.fetchTitle);
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    fetchTitle();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [fetchTitle]);

  return (
    <div>
      <h1> BookTitle: {book.title} </h1>
      <h1> Books: {book.amount} </h1>
      <button onClick={() => updateAmount(10)}> Update Amount </button>
      <div>
        <input type="text" ref={inputRef} />
        <button
          onClick={() =>
            updateTitle(inputRef.current ? inputRef.current.value : "")
          }
        >
          Update Text
        </button>
      </div>
    </div>
  );
};
No.2309
11/03 16:45

edit