npm i zustand
とても便利なので、こちらから入れておきましょう
https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ja
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>
);
};