Can't find what I am doing wrong. If I type the url on the browser the page does load, but the links from the navbar do nothing. I am trying three different ways to use router-link, but makes no differences. It just won't render the page via link. No errors on the console. On the vue devtools the routing displays the correct path.
App.vue:
<template>
<nav class="navbar">
<router-link :to="{ path: '/' }">Home</router-link>
<router-link :to="{name:'TheDashboard'}"> Dashboard</router-link>
<router-link to="/games">Games</router-link>
</nav>
<router-view></router-view>
</template>
router/index.js:
import { createRouter, createWebHistory } from 'vue-router'
import TheHomePage from '#/pages/TheHomePage'
import TheDashboard from '#/pages/TheDashboard'
const routes = [
{
path: '/',
name: 'TheHomePage',
component: TheHomePage
},
{
path: '/dashboard',
name: 'TheDashboard',
component: TheDashboard
},
{
path: '/games',
name: 'TheGames',
component: () => import(/*webpackChunkName: "games" */ '#/pages/TheGames.vue'),
props: true
},
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
main.js:
import { createApp } from 'vue'
import App from '#/App.vue'
import router from '#/router'
import store from '#/store'
const prototype = createApp(App)
prototype.use(router)
prototype.use(store)
prototype.mount('#app')
In the end this was a bug caused by Vue devtools. I removed previous versions and updated to latest, and it is now working. Nothing wrong with the code. I thought I might as well leave the code here, since it might be helpful for other people.
your code seems optimal to me. However, you can use the beforeEach and afterEach hooks to help you to debug your App.
you can read about them here
do something like:
//router/index.js
//...
//const router = ...
router.afterEach((to, from, failure) => {
console.log('to: ', to);
console.log('from: ', from);
if (isNavigationFailure(failure)) {
console.log('failed navigation', failure)
}
});
export router;
Related
I want to show login page outside the layout but unfortuntly i see the sidebar and header on login page sidebar and header should not be on login page please help me how can i resolve that thank u ?
App.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
import Layout from './components/Layouts/Layout.vue'
</script>
<template>
<div id="app">
<Layout></Layout>
</div>
<RouterView />
</template>
<script>
export default {
name: 'App',
components: {
Layout,
}
}
</script>
router\index.js
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'login',
component: Login
},
{
path: '/dashboard',
name: 'dashboard',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/DashBoard.vue')
},
]
})
export default router
Use conditional rendering to hide/show elements based on the current route
<Layout v-if="route.path !== '/'"></Layout>
<script setup>
import { RouterLink, RouterView, useRoute } from 'vue-router'
import Layout from './components/Layouts/Layout.vue'
const route = useRoute();
</script>
Also, not sure why you have two script tags. You don't need to register components with the Composition API (script setup), so you can/should remove the second script
Hi
I just made a website with a darkmode and multilanguage support to test around but I ran into an issue.
the code
I got rid of all things that aren't an issue
portfolio/src/pages/index.tsx
import { useTranslation } from 'react-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
export default () => {
const { t,i18n } = useTranslation('common')
return <div onClick={()=>i18n.changeLanguage(i18n.language=='fr'?'en':'fr')}>
<div>{i18n.language}</div>
<span>{t('debug')}</span>
</div>
}
export async function getStaticProps({ locale }:any) {
return {
props: {
...(await serverSideTranslations(locale, ['common'])),
// Will be passed to the page component as props
},
};
}
portfolio/src/public/locales/en/common.js
{"debug":"english"}
portfolio/src/public/locales/fr/common.js
{"debug":"français"}
portfolio/next-i18next.config.js
const path = require("path");
module.exports = {
debug: false,
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr'],
},
localePath: path.resolve('./src/public/locales'),
};
portfolio/src/pages/_app.tsx
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import {appWithTranslation} from 'next-i18next'
export default appWithTranslation(({ Component, pageProps }: AppProps) => {
return <Component {...pageProps} />
})
The issue
When I do npm run dev and go to http://localhost:3000/fr, the page defaults to french and works good I can swap between languages without problems but when i go to http://localhost:3000/en the t('debug') doesn't translate when the i18n.language changes as intended.
Found what I wanted
So basicaly I need to use a next Link that will change the local and the link
Code application
index.js
//...
export default () => {
const { t,i18n } = useTranslation('common')
return (
<div>
<Link
href={i18n.language=='fr'?'/en':'/fr'}
locale={i18n.language=='fr'?'en':'fr'}
>{i18n.language}</Link>
<div>{t('debug')}</div>
</div>
)
}
//...
result
Now the text changes as intended both in the /fr and /en because it switches between the 2 however the result is far from smooth. It reloads the page and i'd like to avoid that because I use some animations on it.
Found what i wanted part 2
Browsing through the next-i18next documentation I found what I wanted.
solution
I needed to load the props using getStaticProps and in the serverSideTranslation function i needed to pass as argument the array off ALL the language necessary to load the page ['en','fr'] because i switched between the 2
My Navbar component relies on the useRouter function provided by nextjs/router in order to style the active links.
I'm trying to test this behavior using Cypress, but I'm unsure of how I'm supposed to organize it. Cypress doesn't seem to like getRoutePathname() and undefined is returned while within my testing environment.
Here's the component I'm trying to test:
import Link from 'next/link'
import { useRouter } from 'next/router'
function getRoutePathname() {
const router = useRouter()
return router.pathname
}
const Navbar = props => {
const pathname = getRoutePathname()
return (
<nav>
<div className="mr-auto">
<h1>Cody Bontecou</h1>
</div>
{props.links.map(link => (
<Link key={link.to} href={link.to}>
<a
className={`border-transparent border-b-2 hover:border-blue-ninja
${pathname === link.to ? 'border-blue-ninja' : ''}`}
>
{link.text}
</a>
</Link>
))}
</nav>
)
}
export default Navbar
I have the skeleton setup for the Cypress component test runner and have been able to get the component to load when I hardcode pathname, but once I rely on useRouter, the test runner is no longer happy.
import { mount } from '#cypress/react'
import Navbar from '../../component/Navbar'
const LINKS = [
{ text: 'Home', to: '/' },
{ text: 'About', to: '/about' },
]
describe('<Navbar />', () => {
it('displays links', () => {
mount(<Navbar links={LINKS} />)
})
})
Ideally, there'd be a provider for Next.js's useRouter to set the router object and wrap the component in the provider in mount. Without going through the code or Next.js supplying the documentation, here's a workaround to mock useRouter's pathname and push:
import * as NextRouter from 'next/router'
// ...inside your test:
const pathname = 'some-path'
const push = cy.stub()
cy.stub(NextRouter, 'useRouter').returns({ pathname, push })
I've added push because that's the most common use case, which you may also need.
Delab some code changes Vue3-Vite.
I receive error after reboot page in Vue3.
Uncaught ReferenceError: Cannot access 'router' before initialization
router\index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
]
App.vue
<router-link
to="/"
>
<button
type="button"
class="btn btn-outline-primary mx-4"
>
Home
</button>
</router-link>
router\index.js
import { createWebHistory, createRouter } from "vue-router";
const history = createWebHistory();
const routes = [/* Routes*/];
const router = createRouter({ history, routes });
export default router;
add router in main.js
import router from "./router";
createApp(App).use(router).mount("#app");
At no time does it see how you use a router in your app when it is mounted.
In all cases you should do something like
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import { createApp} from 'vue';
const routes = createRouter([
{
path: '/',
name: 'Home',
component: Home
},
)]
const app = createApp(Home);
app.use(routes);
(PS: I'm using Meteor + React + React Router. The application structure is not traditional, I'm making a package-esq application, an example is https://github.com/TelescopeJS/Telescope. I'm trying to do dynamic routing with react router and things are not working out well.)
There be something wrong with browserHistory. Navigation refreshes the page. Going back and forth through the browser buttons refreshes the page.
Example of this, with all codes, are here - https://github.com/dbx834/sandbox
React-Router specific codes follow,
In a core package, with a global export, allow registeration of routes and components
...
// ------------------------------------- Components -------------------------------- //
Sandbox.components = {};
Sandbox.registerComponent = (name, component) => {
Sandbox.components[name] = component;
};
Sandbox.getComponent = (name) => {
return Sandbox.components[name];
};
// ------------------------------------- Routes -------------------------------- //
Sandbox.routes = {};
Sandbox.routes.routes = [];
Sandbox.routes = {
routes: [],
add(routeOrRouteArray) {
const addedRoutes = Array.isArray(routeOrRouteArray) ? routeOrRouteArray : [routeOrRouteArray];
this.routes = this.routes.concat(addedRoutes);
},
};
...
In various implementations (domain specific logic, UI, etc), register components and routes
...
import TodoApp from './components/TodoApp.jsx';
Sandbox.registerComponent('TodoApp', TodoApp);
Sandbox.routes.add([
{ name: 'todoAppRoute', path: 'todo-app', component: Sandbox.components.TodoApp },
]);
...
In the main app
import React from 'react';
import { render } from 'react-dom';
import { Meteor } from 'meteor/meteor';
import { Router, browserHistory } from 'react-router';
import App from './components/App.jsx';
import Homepage from './components/Homepage.jsx';
Sandbox.registerComponent('App', App);
Sandbox.registerComponent('Homepage', Homepage);
Meteor.startup(() => {
const AppRoutes = {
path: '/',
component: Sandbox.components.App,
indexRoute: { name: 'home', component: Sandbox.components.Homepage },
childRoutes: Sandbox.routes.routes,
};
console.log(AppRoutes);
render(
<Router routes={AppRoutes} history={browserHistory} />,
document.getElementById('app-root')
);
});
What is wrong?
I uninstalled all npm packages, meteor packages, updated everything, re-installed latest packages, cleaned out all previous builds and everything works now!
There was something weird somewhere.
If anyone finds themselves in a similar situation, you can try this.
Best