29
loading...
This website collects cookies to deliver better user experience
Vuex
and Redux
, and both of them are quite popular in their framework scope. Vuex
is the preferred and go to state management setup while working with Vue applications. It's actively maintained by the Vue core team and the major v4
of the library just went stable a few months ago. If we look from the Flux
point of view I think vuex implements the pattern as effectively as possible and they also did a great job with the API. I mentioned as effectively as possible because Flux
by design brings some limitations and same goes for vuex too. Let's have a look at the current limitations with Vuex that I faced frequently// in store.ts
const store = createStore({
state() {
return {
count: 0,
};
},
mutations: {
increment(state) {
state.count++; // types will be inferred
},
},
getters: {
doubled(state) {
return state * 2; // types will be inferred
},
},
});
<!-- in component.vue -->
<script>
export default {
computed: {
...mapGetters({
doubled: 'doubled', // types will not be inferred
}),
getDoubled(): number {
return this.$store.getters.doubled; // specifying return type
},
},
};
</script>
<script>
export default {
methods: {
...mapMutations({
increament: 'increament',
}),
inc() {
this.$store.commit('increment');
},
},
};
</script>
// from pinia docs
// in ts types will be inferred automatically
import { defineStore } from 'pinia'
export const useTodoStore = defineStore({
id: 'todos',
state: () => ({
/** @type {{ text: string, id: number, isFinished: boolean }[]} */ // for js files
todos: [],
}),
getters: {
finishedTodos(state) {
// autocompletion! ✨
return state.todos.filter((todo) => todo.isFinished)
},
unfinishedTodos(state) {
return state.todos.filter((todo) => !todo.isFinished)
},
},
actions: {
// any amount of arguments, return a promise or not
addTodo(text) {
// you can directly mutate the state
this.todos.push({ text, id: this.nextId++, isFinished: false })
},
},
})
setup() {
const { finishedTodos } = useTodoStore(); // full type support
},
// from furikaeru
//types
type AlertAPI = {
set: (alert: Alert) => void;
remove: (id: string) => void;
alerts: ComputedRef<Alert[]>;
};
const AlertKey: InjectionKey<AlertAPI> = Symbol();
const alerts = ref<Alert[]>([]);
export const getAlerts = computed(() => readonly(alerts.value));
export interface Alert {
message: string;
icon?: string;
id?: string;
type: 'success' | 'danger' | 'warning';
}
export function setAlerts(alert: Alert) {
if (alerts.value.find((el) => el.message === alert.message)) return;
alerts.value.push({ ...alert, id: uuid() });
setTimeout(() => {
if (alerts.value.length > 0) {
alerts.value.shift();
}
}, 5000);
}
export function removeAlert(id: string) {
const alertIndex = alerts.value.findIndex((el) => el.id === id);
if (alertIndex === -1) return;
alerts.value.splice(alertIndex, 1);
}
export function useAlert() {
return inject(AlertKey) as AlertAPI;
}