Component isn't updating from computed value

40 views Asked by At

I have a generic component linked to a computed value to simulate routing. There is a current page property, and three links, whenever the user clicks on a link, that property gets updated via the renderPage.

Before switching to <script setup> the code worked fine, now, the generic component doesn't seem to do anything.

Here's the code:

<script setup>
import { computed, ref } from "vue";
import HomePage from "./components/HomePage.vue";
import LoginPage from "./components/LoginPage.vue";
import UsersPage from "./components/UsersPage.vue";


const currentPage = ref("Home");

const renderPage = computed(() => `${currentPage.value}Page`)


function showHomePage() {
  currentPage.value = "Home";
}
function showLoginPage() {
  currentPage.value = "Login";
}
function showUsersPage() {
  currentPage.value = 'Users';
}
</script>

<template>
  <header class="header">
    <span class="logo">
      <img src="@/assets/vue-heart.png" width="30" />C'est La Vue
    </span>
    <nav class="nav">
      <a href="#" @click.prevent="showHomePage">Home</a>
      <a href="#" @click.prevent="showUsersPage">Users</a>
      <a href="#" @click.prevent="showLoginPage">Login</a>
    </nav>
  </header>
  <component :is="renderPage" />
</template>

The generic component is able to render the components properly if set manually, but whenever linked to the renderPage computed property, it doesn't work anymore.

The renderPage when added inside a mustache works as expected, updating the string as it should.

1

There are 1 answers

2
Alexander Nenashev On BEST ANSWER

import HomePage from "./components/HomePage.vue"; make a variable HomePage, not something in the the template context named HomePage. To refer to an imported component by name, make an object containing components by name:

const components = {HomePage, LoginPage, UserPage};

Then use it in the template:

  <component :is="components[renderPage]" />

But better is to reference the components directly:


<script setup>
import { computed, ref } from "vue";
import HomePage from "./components/HomePage.vue";
import LoginPage from "./components/LoginPage.vue";
import UsersPage from "./components/UsersPage.vue";


const renderPage = ref(HomePage);


</script>

<template>
  <header class="header">
    <span class="logo">
      <img src="@/assets/vue-heart.png" width="30" />C'est La Vue
    </span>
    <nav class="nav">
      <a href="#" @click.prevent="renderPage = HomePage">Home</a>
      <a href="#" @click.prevent="renderPage = UserPage">Users</a>
      <a href="#" @click.prevent="renderPage = LoginPage">Login</a>
    </nav>
  </header>
  <component :is="renderPage" />
</template>