Vue.js: Failed to generate render function - gulp

I try to run a simple Vue.js, but I constantly receive the following error:
[Vue warn]: It seems you are using the standalone build of Vue.js in
an environment with Content Security Policy that prohibits
unsafe-eval. The template compiler cannot work in this environment.
Consider relaxing the policy to allow unsafe-eval or pre-compiling
your templates into render functions.
main.js:3180 [Vue warn]: Failed to generate render function:
EvalError: Refused to evaluate a string as JavaScript because
'unsafe-eval' is not an allowed source of script in the following
Content Security Policy directive: "default-src 'self'". in
with(this){return _c('div',{attrs:{"id":"app"}})}
(found in )
Yet, I can't understand what is causing this error. I don't seem to use any dynamic templates and everything should be pre-compiled. Here is the code of my application:
import Vue from 'vue'
import VueRouter from 'vue-router'
const Home = Vue.component('home-component', {
render() {
return <div>
<router-link to="/users">Users</router-link>
<router-link to="/about">About</router-link>
</div>
}
})
const Users = Vue.component('users-component', {
render() {
return <p>Users</p>
}
})
const NotFound = Vue.component('not-found-component', {
render() {
return <p>Not Found</p>
}
})
const routes = [
{ path: '/', component: Home },
{ path: '/users', component: Users }
]
const router = new VueRouter({
routes
})
const app = new Vue({
router
}).$mount('#app')
And here is how I process JavaScript files in my gulpfile:
const paths = {
main: 'web/javascript/src/main.js',
allJs: 'web/javascript/**/*.{js,vue}',
resultJs: 'public/assets/javascript/main.js',
};
gulp.task('scripts', function() {
return browserify(paths.main)
.transform(babelify, { presets: ['es2015'], plugins: ["transform-runtime"] })
.transform(vueify)
.bundle()
.pipe(fs.createWriteStream(paths.resultJs))
}
There are seem to be many similar questions on StackOverflow, but none of them helped me.

The broweser is throwing Content Security Policy (CSP) error, to get around this issue you should consider switching to the runtime-only build, which is fully CSP-compliant.
https://v2.vuejs.org/v2/guide/installation.html#CSP-environments
Also, You have return incorrectly written. It should return jsx in pair of paranthesis (). The code below should help
import Vue from 'vue'
import VueRouter from 'vue-router'
const Home = Vue.component('home-component', {
render(h) {
return(
<div>
<router-link to="/users">Users</router-link>
<router-link to="/about">About</router-link>
</div>
)
}
})
const Users = Vue.component('users-component', {
render(h) {
return(
<p>Users</p>
)
}
})
const NotFound = Vue.component('not-found-component', {
render(h) {
return(
<p>Not Found</p>
)
}
})
const routes = [
{ path: '/', component: Home },
{ path: '/users', component: Users }
]
const router = new VueRouter({
routes
})
const app = new Vue({
router
}).$mount('#app')

Related

react-router 6 Navigate to using params

In v5 i have such structure
{
path: '/someurl/:id',
exact: true,
render: ({ params }) => (<Redirect to={`/someurl/extraurl/${params.id}`} />),
}
How to refactor this to V6?
react-router-dom v6 no longer has route props, so you'll need to create a new component to gather the "props", or match.params in this case, and render the redirect as a Navigate component.
const MyRedirect = () => {
const { id } = useParams();
return <Navigate to={`/someurl/extraurl/${id}`} replace />;
};
...
{
path: '/someurl/:id',
element: <MyRedirect />,
}
...
<Route path={obj.path} element={obj.element} />
The accepted answer will work but I'll add my solution too, since it's a bit more dynamic. You can set up a function component that will make use of the useParams hook and the generatePath function so your intended destination gets the params from the initial route (whatever they may be):
import React, { FunctionComponent } from 'react';
import { generatePath, Navigate, useParams } from 'react-router-dom';
interface IProps {
to: string;
replace?: boolean;
state?: any;
}
const Redirect: FunctionComponent<IProps> = ({ to, replace, state }) => {
const params = useParams();
const redirectWithParams = generatePath(to, params);
return (
<Navigate to={redirectWithParams} replace={replace} state={state} />
);
};
export default Redirect;
Using this should work with your first example (and any other routes / redirects with dynamic params).

My first angular app does not work as expected

I started to play around with Angular, I downloaded all the relevant stuff, but I'm getting the following output (I should see some name instead of {{ name }}):
Here is app.component.html:
<input type="text" [(ngModel)]="name">
<p>{{ name }}</p>
Here is app.component.ts:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.styl']
})
export class AppComponent {
name = 'ddd';
}
Here is app.component.spec.ts:
import { TestBed, async } from '#angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'my-first-app'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('my-first-app');
});
it('should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to my-first-app!');
});
});
Couple of things you can check:
Debugging starts from Browser's console tab. Check if you've an error. If yes then click on that error. Angular doc will guide you what mistakes you've made.
Check if you have imported FormsModule in you app.module.ts file.
Alternatively, You can verify if you've a successful started the initial project like this also (this will also confirm that you've error with FormsModule):
In app.component.html file
<input (keyup)="onKey($event)">
<p>{{values}}</p>
In app.component.ts file
values = '';
onKey(event: any) { // without type info
this.values += event.target.value + ' | ';
}
Write something and check if this works. If yes then you've error with FormsModule and not with Angular project.
Note: just to verify in start you can disable the test cases.
A very good start is using the cli to initialize your project.
The Angular CLI makes it easy to create an application that already
works, right out of the box. It already follows our best practices!
First
npm install -g #angular/cli
Then
ng new my-dream-app
Then
cd my-dream-app
Finally
ng serve

Subdomains Laravel Routing and Vue.js

I'm using Laravel 5.4, vue.js 2.3 and vue-router.
Current situation
When example.com is hit, Laravel returns the app view which starts the Vue.app
web.php
Route::get('/', function () {
return view('app');
});
app.js
const routes = [
{ path: '/', component: App },
];
const app = new Vue({
el: '#app',
router,
data () {
return {}
},
});
App.vue
export default {
...
}
What I'm trying to do
If usa.example.com is typed, I would like the alert() in my App.vue to show usa.
If italy.example.com is typed, I would like the alert() in my App.vue to show italy.
I read the documentation of vue-router but I'm not sure wether it is a Laravel issue, a Vue issue or both.
App.vue
export default {
....
created() {
alert('subdomain is ' + $route.params.subdomain)
}
}
VueRouter doesn't keep track of the subdomain.
But, you can get the subdomain from the location and use that in your component's created method:
created() {
let subdomain = location.hostname.split('.').shift();
alert('subdomain is ' + subdomain);
}
The above code is based off of this answer.

How to bulid Application template Vue

I'm new to Vue and to ES6
And I did the following:
import Vue from 'vue'
import VueRouter from 'vue-router'
import $ from 'jquery'
Vue.use(VueRouter)
var App = {};
App.template = `
<main-menu></main-menu>
<router-view></router-view>`;
const header = Vue.component('main-menu', require('./components/app/header.vue'));
const facebook = Vue.component('facebook-gif', require('./components/facebook.vue'));
const router = new VueRouter({
routes: [
{
path: '/',
},
{
path: '/facebook',
component: {
facebook: facebook
}
}
]
});
App.app = new Vue({
router,
render (h) {
return h(`div`, App.template)
}
}).$mount('#app');
But what it's nothing render , I just see the main-menu and router-view tags in my broswer...
And when I edit my html and put there this:
<div id="app">
<main-menu></main-menu>
<router-view></router-view>
</div>
I get this error when I'm trying to enter the facebook route:
[Vue warn]: Failed to mount component: template or render function not defined.
and the facebook template is wrapped with template tag and it's inside a vue file
facebook.vue
<template>
<div>
dsfsdsfdsf
<div v-if="showLogin">
<button v-on:click="login">Log In With Facebook</button>
<span v-if="error">{{ error }}</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
showLogin: true,
error:null,
}
},
methods() {
return {
login() {
}
}
}
}
</script>
But the main-menu component is render...
What is the problem?
EDIT
I downloaded the example like wostex said
I create an App.vue file contain:
<template>
<div id="app">
<main-menu></main-menu>
<router-view></router-view>
</div>
</template>
I edit my html file to contain
I added in app.js
import App from './components/App.vue'
const v = new Vue({
el: "#app",
router,
render: h => h(App)
});
and my html file contain:
<div id="app"></div>
and I get this error:
vue.common.js:436 [Vue warn]: Failed to mount component: template or render function not defined.
found in
---> <Anonymous>
<App> at /opt/lampp/htdocs/gif/resources/assets/js/components/App.vue
<Root>
it happens because the facebook component, when I'm in the main page I don't see the error, only when I enter the facebook route
It seems your first set up was failing because of what build you we're using. For eg:
App.app = new Vue({
router,
render (h) {
return h(`div`, App.template) // this part can be roughly
// translated to `return h(`div`,
// `<one-component></one-component>
// <router-view></router-view>`)` and I believe
// this failed due to the fact that when you pass
// template string to the render method it needs to
// be compiled and your setup didn't account for that.
}
}).$mount('#app');
Your other set up ( as per suggestion of #wostex ) is much better but I think that here you are missing .$mount('#app') at the end of your Vue initialization. So:
const v = new Vue({
router,
render: h => h(App)
}).$mount('#app')
I looked at Laracasts in Jeffry tutorial about Vue
He did there like that:
const router = new VueRouter({
routes: [
{
path: '/',
},
{
path: '/facebook',
component: require('./components/facebook.vue')
}
]
});
and it work's
So thanks every one that tried to help me

Using Jest to test a Link from react-router v4

I'm using jest to test a component with a <Link> from react-router v4.
I get a warning that <Link /> requires the context from a react-router <Router /> component.
How can I mock or provide a router context in my test? (Basically how do I resolve this warning?)
Link.test.js
import React from 'react';
import renderer from 'react-test-renderer';
import { Link } from 'react-router-dom';
test('Link matches snapshot', () => {
const component = renderer.create(
<Link to="#" />
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
The warning when the test is run:
Warning: Failed context type: The context `router` is marked
as required in `Link`, but its value is `undefined`.
You can wrap your component in the test with the StaticRouter to get the router context into your component:
import React from 'react';
import renderer from 'react-test-renderer';
import { Link } from 'react-router-dom';
import { StaticRouter } from 'react-router'
test('Link matches snapshot', () => {
const component = renderer.create(
<StaticRouter location="someLocation" context={context}>
<Link to="#" />
</StaticRouter>
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
Have a look at the react router docs about testing
I had the same issue and using StaticRouter would still require the context which needed more configuration to have it available in my test, so I ended up using the MemoryRouter which worked very well and without any issues.
import React from 'react';
import renderer from 'react-test-renderer';
import { MemoryRouter } from 'react-router-dom';
// SampleComponent imports Link internally
import SampleComponent from '../SampleComponent';
describe('SampleComponent', () => {
test('should render', () => {
const component = renderer
.create(
<MemoryRouter>
<SampleComponent />
</MemoryRouter>
)
.toJSON();
expect(component).toMatchSnapshot();
});
});
The answer of #Mahdi worked for me! In 2023 if you want to test a component that includes <Link> or <NavLink>, we just need to wrap it with the <MemoryRouter> in the test file:
// App.test.js
import { render, screen } from "#testing-library/react";
import MyComponent from "./components/MyComponent";
import { MemoryRouter } from "react-router-dom"; // <-- Import MemoryRouter
test("My test description", () => {
render(
<MemoryRouter> // <-- Wrap!
<MyComponent />
</MemoryRouter>
);
});
my test like this:
import * as React from 'react'
import DataBaseAccout from '../database-account/database-account.component'
import { mount } from 'enzyme'
import { expect } from 'chai'
import { createStore } from 'redux'
import reducers from '../../../reducer/reducer'
import { MemoryRouter } from 'react-router'
let store = createStore(reducers)
describe('mount database-account', () => {
let wrapper
beforeEach(() => {
wrapper = mount(
< MemoryRouter >
<DataBaseAccout store={store} />
</MemoryRouter >
)
})
afterEach(() => {
wrapper.unmount()
wrapper = null
})
})
but I don't konw why MemoryRouter can solve this。
Above solutions have a common default defact:
Can't access your component's instance! Because the MemoryRouter or StaticRouter component wrapped your component.
So the best to solve this problem is mock a router context, code as follows:
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
describe('YourComponent', () => {
test('test component with react router', () => {
// mock react-router context to avoid violation error
const context = {
childContextTypes: {
router: () => void 0,
},
context: {
router: {
history: createMemoryHistory(),
route: {
location: {
hash: '',
pathname: '',
search: '',
state: '',
},
match: { params: {}, isExact: false, path: '', url: '' },
}
}
}
};
// mount component with router context and get component's instance
const wrapper = mount(<YourComponent/>, context);
// access your component as you wish
console.log(wrapper.props(), wrapper.state())
});
beforeAll(() => {
configure({ adapter: new Adapter() });
});
});