1
votes

Why is the action type unknown, and what is the fix?

I know this is a common problem. I searched SO and there are ~20 answers, many of which are related to mapActions. After reading thru most all of those answers, and trying countless variations of mapActions syntax, I still can't figure out what's wrong with my code.

I understand, we are supposed to call dispatch in the component (or module), which then commits a mutation in the Vuex store (which is where the actual value gets changed).

Also, not sure if it's helpful to point out, but I expected to see the actions and mutations in the state pic below, but do not.

Update:

After editeding the code as a couple others suggested, the result is still the same; unknown action type: toggleIsCategoryWheelSpinning,{}

Not sure if it's relevant, but the line where dispatch is called myStore.dispatch("toggleIsCategoryWheelSpinning,{}"); in Wheel.vue is inside a nested function.


enter image description here

Here is my code:

 //Wheel.vue

    <template>
    <div >
        <div id="chart"></div>
    </div>
</template>

<script type="text/javascript" charset="utf-8">
import store from 'vuex'
import { mapActions} from 'vuex'

export default {
    name: "wheel",
    props: {
        wheelCategories: {
            type: Array,
            required: true,
        },
        expressions: {
            type: Array,
            required: true,
        },
    },
    data() {
        return {
        };
    },
    mounted() {
        let myscript = document.createElement("script");
        myscript.setAttribute("src", "https://d3js.org/d3.v3.min.js");
        document.head.appendChild(myscript);
        myscript.onload = this.createWheel(this.wheelCategories,this.expressions, this.$store);
    },
    methods: {
        ...mapActions(['toggleIsCategoryWheelSpinning']),   
        created(){
            this.toggleIsCategoryWheelSpinning       
        },

        createWheel: function (wheelCategories,expressions, myStore) {
            var padding = { top: 20, right: 40, bottom: 20, left: 20 },
                w = 500 - padding.left - padding.right,
                h = 500 - padding.top - padding.bottom,
                r = Math.min(w, h) / 2,
                rotation = 0,
                oldrotation = 0,
                picked = 100000,
                oldpick = [],
                color = d3.scale.category20();
            
            var svg = d3
                .select("#chart")
                .append("svg")
                .data([wheelCategories])
                .attr("width", w + padding.left + padding.right)
                .attr("height", h + padding.top + padding.bottom);
            
            var container = svg
                .append("g")
                .attr("class", "chartholder")
                .attr(
                    "transform",
                    "translate(" +
                        (w / 2 + padding.left) +
                        "," +
                        (h / 2 + padding.top) +
                        ")"
                )
                .style({ cursor: "grab" });

            var vis = container.append("g");

            var pie = d3.layout
                .pie()
                .sort(null)
                .value(function (d) {
                    return 1;
                });

            var arc = d3.svg.arc().outerRadius(r);

            var arcs = vis
                .selectAll("g.slice")
                .data(pie)
                .enter()
                .append("g")
                .attr("class", "slice");
            
            arcs.append("path")
                .attr("fill", function (d, i) {
                    return color(i);
                })
                .attr("d", function (d) {
                    return arc(d);
                });

            // add the text
            arcs.append("text").attr("transform", function (d) {
                d.innerRadius = 0;
                d.outerRadius = r;
                d.angle = (d.startAngle + d.endAngle) / 2;
                return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")translate(" + (d.outerRadius -10) +")";
            })
            .attr("text-anchor", "end")
                .text(function (d, i) {
                    return wheelCategories[i].label;                 
                });

            container.on("click", spin);  

            function spin(d) {
                container.on("click", null);
                //the following line gives the "unknown action"
                myStore.dispatch("toggleIsCategoryWheelSpinning,{}");
                console.log('dispatch finished');

                //all slices have been seen, all done
                if (oldpick.length == wheelCategories.length) {
                    document.getElementById("spinResponse"
                    ).innerHTML = `out of spins`;
                    container.on("click", null);
                    return;
                }

                var ps = 360 / wheelCategories.length,
                    pieslice = Math.round(1440 / wheelCategories.length),
                    rng = Math.floor(Math.random() * 1440 + 360);

                rotation = Math.round(rng / ps) * ps;

                picked = Math.round(
                    wheelCategories.length - (rotation % 360) / ps
                );
                picked =
                    picked >= wheelCategories.length
                        ? picked % wheelCategories.length
                        : picked;

                if (oldpick.indexOf(picked) !== -1) {
                    d3.select(this).call(spin);
                    return;
                } else {
                    oldpick.push(picked);
                }

                rotation += 90 - Math.round(ps / 2);

                let index = Math.floor(Math.random() * expressions.length); // 10  returns a random integer from 0 to 9

                vis.transition()
                    .duration(3000)
                    .attrTween("transform", rotTween)
                    .each("end", function () {
                        oldrotation = rotation;
                        container.on("click", spin);
                    });
            }

            //make arrow
            svg.append("g")
                .attr(
                    "transform",
                    "translate(" +
                        (w + padding.left + padding.right) +
                        "," +
                        (h / 2 + padding.top) +
                        ")"
                )
                .append("path")
                .attr(
                    "d",
                    "M-" +
                        r * 0.15 +
                        ",0L0," +
                        r * 0.05 +
                        "L0,-" +
                        r * 0.05 +
                        "Z"
                )
                .style({ fill: "black" });

            //draw spin circle
            container
                .append("circle")
                .attr("cx", 0)
                .attr("cy", 0)
                .attr("r", 60)
                .style({ fill: "white", cursor: "grab" });

            //spin text
            container
                .append("text")
                .attr("x", 0)
                .attr("y", 15)
                .attr("text-anchor", "middle")
                .text("SPIN ME!")
                .style({
                    "font-weight": "bold",
                    "font-size": "25px",
                    cursor: "grab",
                });

            function rotTween(to) {
                var i = d3.interpolate(oldrotation % 360, rotation);
                return function (t) {
                    return "rotate(" + i(t) + ")";
                };
            }

            function getRandomNumbers() {
                var array = new Uint16Array(1000);
                var scale = d3.scale
                    .linear()
                    .range([360, 1440])
                    .domain([0, 100000]);

                if (
                    window.hasOwnProperty("crypto") &&
                    typeof window.crypto.getRandomValues === "function"
                ) {
                    window.crypto.getRandomValues(array);
                    console.log("works");
                } else {
                    //no support for crypto, get crappy random numbers
                    for (var i = 0; i < 1000; i++) {
                        array[i] = Math.floor(Math.random() * 100000) + 1;
                    }
                }

                return array;
            }
        }
    }
    
};

//end code for wheel
</script>

<style type="text/css" scoped>
text {
    font-size: 15px;
    pointer-events: grab;
}
#chart {
    /* cursor: grab; */
    margin: 0 auto;
    border: 10px;
}
#question {
    text-align: center;
}
#question h1 {
    font-size: 50px;
    font-weight: bold;
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    /* position: absolute; */
    padding: 0;
    margin: 0;
    top: 50%;
    -webkit-transform: translate(0, -50%);
    transform: translate(0, -50%);
}

#spinResponse {
    font-size: 30px;
    text-align: center;
    width: 500px;
    padding-bottom: 30px;
    background-color: rgb(129, 19, 19);
    font-weight: bold;
}

</style>

the vuex store

// store/index.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const foodCategories = [
   //...
];

const expressions = [
   //...
];

const isCategoryWheelSpinning = false;

export default new Vuex.Store({
  state: {
    foodCategories,
    expressions,
    isCategoryWheelSpinning,
  },
  getters: {
  },    
  actions: {
    toggleIsCategoryWheelSpinning(context,payload){
        context.commit("toggleIsCategoryWheelSpinning",payload);
    }
  },
  mutations: {
   toggleIsCategoryWheelSpinning(state, payload) {
      state.isCategoryWheelSpinning = !isCategoryWheelSpinning;
    },
  },
});

and the main.js

// src/main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store';

Vue.config.productionTip = false

new Vue({
  store,
  render: h => h(App),
}).$mount('#app')
3
An action is called with two parameters: name, which is a string in the form of {module/}{action} (with module names when you're using modules) and payload, which can be an object (or array, which is still an object) or any primitive (string, boolean, number, etc...). So call it as dispatch("toggleIsCategoryWheelSpinning", {}) if you want to call it with an empty object as payload. You've placed the payload inside the name parameter and it results into a string which doesn't map onto a known action.tao
@tao , Your comment lead to (is) the answer. Thank you.greg
Welcome. That's why I wrote it :). I didn't post it as an answer as I believe you could have spotted this yourself if you spent more time looking at the documentation. From where I see it, the error is pretty straight forward so, in my opinion, your question is not likely to help future users. Therefore, according to SO rules (as I understand them), it shouldn't be answered. I realize I'm being subjective here but hey, I get to choose where I set the bar for considering a question worth answering. When it's not, I just help out by pointing in the right direction, if I see it. Happy hollidays!tao

3 Answers

1
votes

your action name mismatches. It should be same for your code. Try to use :...mapActions(["toggleIsCategoryWheelSpinning"] for importing the action

0
votes

In your actions in the store, there is no action called action_toggleIsCategoryWheelSpinning, but there is one called toggleIsCategoryWheelSpinning, so in your mapActions you should import that:

methods: {
  mapActions(['toggleIsCategoryWheelSpinning'])
}
0
votes

The comment from @Tao (see below) lead to (is) the answer; specifically the bold text.

The following code edits fixed the problem.

In Wheel.vue, edit the methods section

...mapActions(['toggleIsCategoryWheelSpinning']),   
created(){
    this.toggleIsCategoryWheelSpinning       
},

When dispatch is called, changed from the first line to the second.

myStore.dispatch("toggleIsCategoryWheelSpinning,{}");    
myStore.dispatch("toggleIsCategoryWheelSpinning",{});

An action is called with two parameters: name, which is a string in the form of {module/}{action} (with module names when you're using modules) and payload, which can be an object (or array, which is still an object) or any primitive (string, boolean, number, etc...). So call it as dispatch("toggleIsCategoryWheelSpinning", {}) if you want to call it with an empty object as payload. You've placed the payload inside the name parameter and it results into a string which doesn't map onto a known action. – tao 30 mins ago