My store as below
import { create } from "zustand";
type State = {
name: string;
age: number;
};
type Action = {
updateName: (name: State['name']) => void;
updateAge: (age: State['age']) => void
};
const initialState: State = {
name: 'bob',
age: 18,
};
export const useTempStore = create<State & Action>((set) => {
return {
...initialState,
updateName: (name) => set(() => ({ name })),
updateAge: (age) => set(() => ({ age })),
}
});
Now, I wanna persist store to server, so I changed the code as below
export const useTempStore = create<State & Action>((set) => {
return {
...initialState,
updateName: (name) => set(() => {
request(name);
return { name }
}),
updateAge: (age) => set(() => {
request(age);
return { age }
}),
}
});
const request = (data) => {
// Send XHR to server
};
But if I have a lot of state, I will have to call request
in every action. How can I make it call request
when very action execute?
What you can do is to subscribe to store changes to fire side-effect.
export const useTempStore = create<State & Action>((set) => {
return {
...initialState,
updateName: (name) => set(() => {
return { name }
}),
updateAge: (age) => set(() => {
return { age }
}),
}
});
useTempStore.subscribe((state) => {
request(state);
})
const request = (data) => {
// Send XHR to server
};
However in this case you will have to send the whole state of the store every time it changed.
If you want to make requests with individual fields of the store, you will need to figure out somehow which field you want to update. In this case your original code is not bad at all. But if you want to decouple side effect logic from state actions you can use subscribe with selectors
import { subscribeWithSelector } from 'zustand/middleware'
export const useTempStore = create<State & Action>(subscribeWithSelector((set) => {
return {
...initialState,
updateName: (name) => set(() => {
return { name }
}),
updateAge: (age) => set(() => {
return { age }
}),
}
}));
// repeat for every field
useTempStore.subscribe(
state => state.name,
(name) => {
request(name);
}
);
const request = (data) => {
// Send XHR to server
};
It doesn't make the code shorter, but probably make it a bit cleaner.