In my opinion, there are three scenarios where getters can provide advantages over directly accessing the state:
- Firstly, getters have the capability to return internal data in a more suitable format compared to how it is stored in the state. By performing this kind of transformation within your Vuex store, you can maintain the cleanliness of your components. For instance:
// Although setters are typically used here, this example illustrates...
const state = {
values: {
2014: 1000,
2015: 2000,
2016: 3000,
2017: 4000,
2018: 5000,
2019: 6000,
2020: 7000
},
startYear: 2016,
endYear: 2019
}
const getters = {
// Outputs something like [3000, 4000, 5000, 6000]
currentValues (state) {
const years = Object.keys(state.values);
years.sort();
return years
.filter(year => year >= state.startYear && year <= state.endYear)
.map(year => state.values[year]);
}
}
- Getters simplify the process of returning copies of data instead of the actual data, preventing accidental modifications to the store without using mutations. Utilizing methods like lodash deepClone or
Object.assign
for shallow objects allows you to create duplicates that can be altered independently in your component without affecting the store.
const state = {
values: {
2014: 1000,
2015: 2000,
2016: 3000,
2017: 4000,
2018: 5000,
2019: 6000,
2020: 7000
},
}
// Within your component
const values = this.$store.state.values;
values[2021] = 8000;
// Unexpectedly modifying the store? Avoid that with a getter.
// Instead, utilize a getter
import { cloneDeep } from 'lodash-es';
const getters = {
values (state) {
return cloneDeep(state.values);
}
}
// Adding 2021 in your component won't impact the state, preventing unintended side effects
- Getters enable separation between the internal state of your Vuex store and the components that utilize it. It establishes a contract between the component and the store, allowing you to modify either component structure or store internals independently, facilitating code refactoring. While setting up initial getters may involve some boilerplate, you can streamline the process by creating a function that generates these getters automatically. If a getter requires complex logic beyond simply returning the state, you can customize it rather than tracking down all occurrences of direct state usage.
function generateGetters(keys) {
return keys.reduce((acc, key) => {
acc[key] = (state) => state[key];
return acc;
}, {});
}
const getters = {
...generateGetters(['values', 'url', 'someOtherKey'])
}