0
votes

I can't get to work in Vue3 this: Counter1 emits value to main App page, App page feeds props of Counter2 component (so Counter2 should basically display data emitted by Counter1):

https://codesandbox.io/s/priceless-ishizaka-md3el?file=/src/components/Counter2.vue

I can't get it to work and I guess there's more job to be done in Counter2 (I tried with reactive objects etc but no luck).

I have the same example written in Vue2 (one-pager) that you can check out here:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
</head>
<body>

<div id="app">  
    <Counter1  @counted="handleCount"></Counter1>
    <Counter2 :received="clicksReceivedAndPassedToCounter2"></Counter2>
</div>

<script>

Vue.component('Counter1', {
 template: `<button @click="handleClick">Clicked {{ clicks }} times</button>`,
 data: () => ({
    clicks: 0
 }),
 methods: {
    handleClick() {
        this.clicks++;
        this.$emit('counted', this.clicks);
    }
 }
});  

Vue.component('Counter2', {
 template: `<p>Counter2 received: {{received}}</p>`,
 props: {
     'received': {
         type: Number,
         default: 0,
         required: true
     }
 }
}); 
 
new Vue({
    el: '#app',
    data() {
        return {
            clicksReceivedAndPassedToCounter2: 0
        }
    },
    methods: {
        handleCount(clicksReceived) {
            this.clicksReceivedAndPassedToCounter2 = clicksReceived;
        }
    }
});
 
</script>
</html>
1

1 Answers

1
votes

You're missing to add the state in the template in the App component :

  <Counter2 :received="clicksReceivedAndPassedToCounter2"></Counter2>

should be :

    <Counter2 :received="state.clicksReceivedAndPassedToCounter2"></Counter2>

If you want to get rid of state in the template and keep the reactivity, you could use toRef as follow :

<template>
  <Counter1 @counted="handleCount"></Counter1>
  <p>Main page received: {{ valCounter2}}</p>
  <Counter2 :received="valCounter2"></Counter2>
</template>

<script>
import { reactive, toRef } from "vue";
import Counter1 from "./components/Counter1.vue";
import Counter2 from "./components/Counter2.vue";
export default {
  name: "App",
  components: {
    Counter1,
    Counter2,
  },
  setup() {
    const state = reactive({
      clicksReceivedAndPassedToCounter2: 0,
    });
    function handleCount(clicksReceived) {
      state.clicksReceivedAndPassedToCounter2 = clicksReceived;
    }
    return {
      valCounter2: toRef(
        state,
        "clicksReceivedAndPassedToCounter2"
      ),
      handleCount,
    };
  },
};
</script>