Onyx
Onyx

Reputation: 5772

Should this logic be placed in Vuex store? I have trouble figuring out when something should be in in store or in the local component state

Currently, I am using the Vuex store for my authentication logic and I understand why being able to access stuff like user token, user id and username from anywhere in my application is extremely useful. I'm 100% sure that the authentication logic belongs to the store.

However, I'm currently playing around with Google Maps and have made a component which has a Google map in it and 3 functions for displaying, adding and removing Google markers from the map. Now I can't figure out if I should move this logic to the Vuex store. I think I will might have to use what is inside the markers: [] property in some other components in the future but everything else seems like it won't be used in any other components.

One of the pros of using Vuex store in this case is that it would make this component more readable and all my logic will be in one place but I'm not sure if that warrants moving the logic.

<template>
    <div class="container">
        <div class="map">
            <GmapMap
                @click='addMarker'
                :center="center"
                :zoom="zoom"
                :map-type-id="map"
                style="width: 100%; height: 800px"
            >
            <GmapMarker
                :key="index"
                v-for="(marker, index) in markers"
                :position="marker"
                :clickable="true"
                :draggable="false"
                @click="removeMarker(index)"
            />
            </GmapMap>
        </div>
    </div>
</template>

<script>
    import axios from 'axios'
    export default {
        data: function() {
            return {
                markers: [],
                center: {lat: 42.150527, lng: 24.746477},
                zoom: 15,
                map: 'roadmap'
            }
        },
        methods: {
            addMarker(event){
                axios.post('/location', {
                    userId: this.$store.state.auth.userId,
                    marker: event.latLng
                }).then(response => {
                    this.markers.push({ 'id': response.data.locations.id,
                                        'lat': response.data.locations.lat,
                                        'lng': response.data.locations.lng})
                }).catch((error) => console.log(error));
            },
            removeMarker(index){
                const markerId = this.markers[index].id
                this.markers.splice(index, 1);

                axios.post('/deleteLocation', {
                    userId: this.$store.state.auth.userId,
                    markerId: markerId
                })
            }
        },
        mounted(){
            axios.get('/location', {
                userId: 1
            }).then(response => {
                this.markers = response.data.locations
            }).catch((error) => console.log(error));
        }
    }
</script>

Upvotes: 3

Views: 977

Answers (1)

Harshal Patil
Harshal Patil

Reputation: 20950

TLDR: Use local state.

Precursor: This decision can always get tricky. Before you attempt to answer this question, think about UI as a function of state i.e. UI = F(state). This is how Elm is built. What it means is that some data X should be part of your central store (Vuex/Redux) when it determines the present view/UI of your overall application and the data itself can stand on its own.

Solution: In this case, think about markers. Should data markers really exist on its own? Is there some UI component (besides the three components in question) of your entire application that can use marker independently on its own? Is data markers complete in itself? Probably yes or no. If you think more as yes, then you can put it inside Vuex otherwise use local component state.

To be more specific, markers together with three functions make a more cohesive unit. So instead of exposing markers as data, expose three functions keeping markers hidden. There are two ways you can do this. First, create one UI-less Vue component (simplified Vuex) that has three functions exposed.

Or as a second approach, Vue.js has provided a better solution for exactly this type of problem - Dependency injection With dependency injection, you can allow children to access ancestor component's data which is exactly what you need in this case. Of course, it also has its own pro and cons but that is a topic for another day.

Note: Alternately, you can also think that these three components GmapMap, GmapMarker, and their parent will always exist together. GmapMarker doesn't make sense on its own without GmapMap, so it is better to keep that state locally. You can then create a separate reusable module of these components, publish to NPM and use it in other applications.

Upvotes: 6

Related Questions