JSFiddle - React, Tailwind, and code Playground

by skirtle

HTML

<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<div id="app">
  <div v-for="i in 3" :key="i">
    <input type="radio" v-model="id" :value="i"> {{ i }}
  </div>
  <details-panel :product-id="id"></details-panel>
</div>

CSS

.panel {
  border: 1px solid #ccc;
  margin: 10px;
}

JavaScript

const DetailsPanel = {
  template: `
    <div class="panel">
      {{ track() }}
      <div><button @click="expanded = !expanded">Toggle Details</button></div>
      <div v-if="expanded">
        <div v-if="product">
          <p><strong>Name:</strong> {{ product.name }}</p>
          <p><strong>Size:</strong> {{ product.size }}</p>
        </div>
        <div v-else>
          Loading...
        </div>
      </div>
    </div>
  `,
  
  props: ['productId'],
  
  data () {
    return {
      expanded: false,
      productCache: {}
    }
  },
  
  computed: {
    product () {
      return this.productCache[this.productId]
    }
  },
  
  methods: {
    track () {
      console.log('track')
      return ''
    }
  },
  
  watch: {
    productId: {
      flush: 'pre',
      immediate: true,
      
      handler () {
        const cache = this.productCache
        const productId = this.productId
        const product = cache[productId]
        
        if (cache[productId]) {
          return
        }
        
        // Pretend HTTP request
        setTimeout(() => {
          cache[productId] = {
            name: 'Product ' + productId,
            size: 'SML'.charAt(productId - 1)
          }
        }, 1000)
      }
    }
  }
}

Vue.createApp({
  components: {
    DetailsPanel
  },
  
  data () {
    return {
      id: 1
    }
  }
}).mount('#app')