Ace
Ace

Reputation: 450

Props arguments are not reactive in setup

I'm trying to develop a component that compiles the given html; I succeeded with constant html texts, but I can't make this work with changing html texts.

main.js

app.component("dyno-html", {
  props: ["htmlTxt"],
  setup(props) {
    watchEffect(() => {
      console.log(`htmlText is: ` + props.htmlTxt);
      return compile(props.htmlTxt);
    });
    return compile(props.htmlTxt);
  },
});

Home.js

<template>
  <div class="home">
    <dyno-html
      :htmlTxt="html2"
      :bound="myBoundVar"
      @buttonclick="onClick"
    ></dyno-html>
    -------------
    <dyno-html
      :htmlTxt="html"
      :bound="myBoundVar"
      @buttonclick="onClick"
    ></dyno-html>
  </div>
</template>

<script>
export default {
  name: "Home",
  components: {},
  data: function() {
    return {
      html: "",
      html2: `<div> Static! <button @click="$emit('buttonclick', $event)">CLICK ME</button></div>`
    };
  },
  mounted() {
    // get the html from somewhere...
    setTimeout(() => {
      this.html = `
        <div>
          Dynamic!
          <button @click="$emit('buttonclick', $event)">CLICK ME</button>
        </div>
      `;
    }, 1000);
  },
  methods: {
    onClick(ev) {
      console.log(ev);
      console.log("You clicked me!");
      this.html2 = "<b>Bye Bye!</b>";
    },
  },
};
</script>

Outcome: Outcome

Console: Console output

It seems the changes of htmlText arrives to setup function, but it doesn't affect the compile function!

Upvotes: 1

Views: 353

Answers (1)

Estus Flask
Estus Flask

Reputation: 223259

This is the expected behaviour because prop value is read once and results in static render function.

Prop value should be read inside render function. It can be wrapped with a computed to avoid unneeded compiler calls:

const textCompRef = computed(() => ({ render: compile(props.htmlTxt) }));
return () => h(textCompRef.value);

Upvotes: 1

Related Questions