How can I get props code hints in vscode(volar) when I use Vue3 component as a property of an object? - vuejs3

I write an vue component, and has two ways to import.
./src/components/popper
import Root from './src/components/Root.vue'
import Anchor from './src/components/Anchor.vue'
export default {
Root,
Anchor,
}
export const PopperRoot = Root
export const PopperAnchor = Anchor
So I can import and use in two ways
import Popper, { PopperRoot, PopperAnchor } from './src/components/popper'
<template>
<Popper.Root>
<Popper.Anchor />
</Popper.Root>
</template>
or
<template>
<PopperRoot>
<PopperAnchor />
</PopperRoot>
</template>
only the latter one can get prompt when input props.
I'm confused, I don't know what volar's code hints are based on and how do I fix it?

Related

Vue - using props on custom elements fails using createApp and mount?

We would like to pass props to custom elements that uses createApp
// index.html
<div id="my-root">
<my-element prop1="abc"></my-element>
</div>
// my-element.vue
<script lang="ts" setup>
const props = defineProps<{ prop1: number }>();
</script>
<template>
{{props.prop1}}
</template>
This works fine, but as our custome element get bigger we would like to register components and use e.g pinia and other tools. Do use those we need to add createApp and mount it. But then prop1 is always undefined
// main.ts
import ...<lots of imports>
import AppCe from "./AppWebComponent.ce.vue";
import { createPinia } from "pinia";
// Adding code below is causing prop1 to be undefined - if we skip this part, prop1 works fine
const pinia = createPinia();
const app = createApp(App);
app.use(pinia).use(ConfirmDialog);
app.component(...<lots of components>);
app.mount("#my-root");
const ceApp = defineCustomElement(AppCe);
customElements.define("my-element", ceApp);
update:
Here's a sample without: https://stackblitz.com/edit/vue3-script-setup-with-vite-56rizn?file=src/my-element/my-element-main.js
And here's a sample with the createApp: https://stackblitz.com/edit/vue3-script-setup-with-vite-gtkbaq?file=index.html
Any idea on how we could solve this?
We have a fallback, that is to do a getElementById and read the attribute value in the mounted callback - but that is not an optimal solution.
Thanks for any ideas!
update2:
Here's an attempt using #duannex suggestion. We're getting closer, the app is availible, components registered, but still no sigar. : https://stackblitz.com/edit/vue3-script-setup-with-vite-ofwcjt?file=src/my-element/defineCustomElementWrapped.js
Based on update2 with the wrapped defineCustomElement; Just pass the props to the render function:
render() {
return h(component, this.$props)
},
https://stackblitz.com/edit/vue3-script-setup-with-vite-vfdnvg?file=src/my-element/defineCustomElementWrapped.js

How to get current route via useRoute outside of router-view component

How can I get the current route using useRoute for a component that's outside of the <router-view />? Is this possible?
Breadcrumbs.vue
<script setup>
import {useRoute} from 'vue-router'
const route = useRoute()
console.log(route.name) // undefined
</script>
App.vue
<template>
<Breadcrumbs />
<router-view />
</template>
The alternative is that I have to put <Breadcrumbs /> at the top of every single view component, and I was hoping to avoid that and instead just include it once in my App.vue
route.name is undefined in your example because that's the initial value when the component is rendered before the route has resolved.
For the component to reactively update based on the current route, use a watcher (e.g., watch or watchEffect):
import { watchEffect } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
watchEffect(() => {
console.log(route.name)
})
demo
In your main file, try to mount app like this
router.isReady().then(() => {
app.mount('#app');
});
then useRoute() should be ready in your component

Import .stories file into another .stories file with Storybook?

Can you import one .stories file into another .stories with Storybook?
Eg I have
/component1/component1.tsx
/component1/component1.stories.tsx
/component2/component2.tsx
/component2/component2.stories.tsx
I would like to also have a story for all of my components:
In /all-components/all-components.stories.tsx
import * as React from 'react';
import Component1Story from '../component1/component1.stories.tsx';
import Component2Story from '../component2/component2.stories.tsx';
export const Test = () => {
return (
<div>
<Component1Story />
<Component2Story />
</div>
);
};
export default {
title: 'Components',
};
I get this error:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of storyFn.
this should be doable as your stories are just React components. Your problem is happening because you're trying to import the default from your module, which is actually just an object:
export default {
title: 'Components',
};
All stories are named exports, and you should import them with destructuring:
import { Component1Story } from '../component1/component1.stories';
import { Component2Story } from '../component2/component2.stories';
I created an example for you which shows a working scenario here.
p.s. It's interesting to know that starting with Storybook 6 there's a new mechanism to simplify the creation and reuse of stories so stay tuned! It's called Args.

problem with react-quill library with next.js project

I'm running into a weird problem. I'm using NextJS for its server-side rendering capabilities and I am using ReactQuill as my rich-text editor. To get around ReactQuill's tie to the DOM, I'm dynamically importing it. However, that presents another problem which is that when I try to access the component where I'm importing ReactQuill via a anchor link is not working but I can access it via manually hit the route. Here is my directories overview,
components/
crud/
BlogCreate.js
pages/
admin/
crud/
blog.js
index.js
blogs/
index.js
In my pages/admin/index.js
...
<li className="list-group-item">
<Link href="/admin/crud/blog">
<a>Create Blog</a>
</Link>
</li>
...
In my pages/admin/crud/blog.js
import BlogCreate from "../../../components/crud/BlogCreate";
...
<div className="col-md-12">
<BlogCreate />
</div>
In my components/crud/BlogCreate.js
import dynamic from "next/dynamic";
const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });
import "../../node_modules/react-quill/dist/quill.snow.css";
...
<div className="form-group">
<ReactQuill
value={body}
placeholder="Write something amazing..."
onChange={handleBody}
/>
</div>
in order to use import "../../node_modules/react-quill/dist/quill.snow.css" in components/crud/BlogCreate.js I use #zeit/next-css and here is my next.config.js
const withCSS = require("#zeit/next-css");
module.exports = withCSS({
publicRuntimeConfig: {
...
}
});
Problem
when I click the Create Blog it should be redirect me http://localhost:3000/admin/crud/blog but it just freeze.
But if I manually hit http://localhost:3000/admin/crud/blog then it go to the desire page and work perfect.
And as soon as I manually load that page then Create Blog works. Now I really don't understand where is the problem? Because it show no error that's why I haven't no term to describe my problem that's why I give all the nasty code and directories which I suspect the reason of this error.
It's hard to give you any solution without seeing the entire project(As you mentioned that it shows no error).
You may remove the #zeit/next-css plugin because Next.js 9.3 is Built-in Sass Support for Global Stylesheets. You can use it for css also.
Create a pages/_app.js file if not already present. Then, import the quill.snow.css file:
import "../../node_modules/react-quill/dist/quill.snow.css";
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
If it gives any error then you can create a directory/file to copy-paste the quill.snow.css code in that file.
pages/
_app.js
styles/
quill_style.css
Then import the file in _app.js like,
import "../styles/styles_quill.css";
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
Eventually you can import your custom gobal css here also.
If although the problem remains then provide your git repository. happy coding ✌️
First: remove your #zeit/next-css setup not needed anymore since next.js version 10.
Second: update nex.js to version 10 you could then use regular import on your modules.
import "../../node_modules/react-quill/dist/quill.snow.css";
By the way, I had the same issue with your Nextjs course. ;)

CSS not changing when using React Router to route to another component

When I route my app to another component by using react-router-dom, the CSS doesn't change.
This is a minimalistic version of the code to demonstrate
App.js
import React from 'react';
import Home from './Home';
function App() {
return (
<div>
<Home></Home>
</div>
);
}
export default App;
Home.js
import React from 'react';
import './Home.css';
const Home = () => {
return (
<h1>Home</h1>
);
}
export default Home;
Home.css
body {
background-color: blue;
}
Dashboard.js
import React from 'react';
import './Dashboard.css';
import React from 'react';
import './Dashboard.css';
const Dashboard = () => {
return (
<div className='content'>
<h1>Dashboard</h1>
</div>
);
}
export default Dashboard;
Dashboard.css
.content {
display: flex;
align-content: center;
align-items: center;
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import Dashboard from './Dashboard';
import * as serviceWorker from './serviceWorker';
import { BrowserRouter as Router, Route } from 'react-router-dom';
ReactDOM.render(
<Router>
<div>
<Route exact path='/' component={App} />
<Route path='/dashboard' component={Dashboard} />
</div>
</Router>, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: ...
serviceWorker.unregister();
When I do /dashboard, it loads the Dashboard component, but it keeps the previous CSS that was loaded from the Home component that resides the App component. The background stays blue. I want that when I route to another component because I changed the URL, it loads whatever CSS that new component has attached to it and gets rid of whatever CSS was before. Is that possible?
Edit: I have made an example in CodeSandbox to illustrate. It's a little different from the code above due to the limitations of the playground, but the functionality is the same.
From what can be seen, importing as a module ends up importing it globally. If we comment the line import Home from "./Home"; the blue background disappears. Just importing the component, imports the whole CSS despite the CSS being imported in a modular way. I'm not sure if I am missing something.
Edit 2:
Here are the different solutions I tried:
CSS Modules, but the body style was still globally loaded.
Styled components don't let me modify the body or html selectors CSS. They require me to create a <div> element and
then have that element span the whole body which I would style
as if it was the body. Which is a workaround I don't want to use because for that I rather use CSS Modules for the whole body spanning .
Inline styling also doesn't let me modify the body or html selectors CSS. I would also need to use a workaround like a body spanning <div> as in Styled components.
The problem
When you import a css like you're doing here
import './Home.css';
you're importing it in a global scope, which means it will not disappear once imported.
The solutions
CSS Modules
What you want is either CSS Modules, which is used like this:
import styles from './Home.css';
<a className={styles.myStyleClass}>Hello</a>
Styled components
or a CSS-in-js framework such as styled components which is used like this:
import styled from 'styled-components';
const MyStyledElement = styled.a`
color: blue;
`;
<MyStyledElement>Hello</MyStyledElement>
Regular objects / inline styling
or just "regular" CSS-in-js like:
const myStyle = {
color: blue;
}
<a style={myStyle}>Hello</a>
There are plenty of options when it comes to styling, these alternatives are popular ones that I encourage you to explore and see which you enjoy.
After doing some more tests I have concluded that as of now it is not possible to change whatever CSS styles have been applied to a <body> or <html> selector in an React SPA when a CSS file is already loaded and one uses React Router to render other components. I still appreciate the answers and the time taken to help me find a solution. They are still valid answers if we are not talking about the <body> or <html> node in an HTML document. From them I learned about other ways to use CSS in React. I modified the original post with the solutions I tried.
What ended working was modifying the DOM styles with JavaScript whithin the component itself.
Home.js
import React from "react";
const Home = () => {
// Modify the DOM Styles with JavaScript
document.body.style.backgroundColor = "blue";
// Or uncomment below to modify the
// document root background color
// which in this case would be <html>
//document.bgColor = "blue";
// Or modify the root tag style of the document instead of the
// <body> (<html> in this case)
//document.documentElement.setAttribute('style', 'background-color: green');
return (
<div>
<h1>Home</h1>
<form action="/dashboard">
<input type="submit" value="Go to Dashboard" />
</form>
</div>
);
};
export default Home;
Here is a working example:
Where my app wasn't loading style sheets and the like. However, I was importing my assets directly into my index.html entry point.
By replacing the links with absolute paths as per this documentation, my problem was resolved.
For me, this meant changing
<head>
<link rel="stylesheet" href="./style.css" ></link>
</head>
to this:
<head>
<link rel="stylesheet" href="/style.css" ></link>
</head>
I'm not sure if the same thing would work for your import statements, but it is worth a shot.
More info: styles-not-working-with-react-router

Resources