In Vuejs 3 I want to use the render() function to create a VNode, passing it a Vue Component. This component varies depending on the current route.
In vite.js I haven't found a way to import a component dynamically inside my ViewComponent computed function.
With webpack I could normally use return require(`./pages/${matchingPage}.vue`).default, but this is not possible with vitejs as I will get a Require is not a function error.
So I tried return import(`./pages/${matchingPage}.vue`) but it returns a Promise, not a Component
//main.js
import {createApp, h} from 'vue'
import routes from './routes'
const SimpleRouterApp = {
data: () => ({
currentRoute: window.location.pathname
}),
computed: {
ViewComponent () {
const matchingPage = routes[this.currentRoute] || '404'
return import(`./pages/${matchingPage}.vue`)
}
},
render () {
return h(this.ViewComponent)
},
created () {
window.addEventListener('popstate', () => {
this.currentRoute = window.location.pathname
})
}
}
createApp(SimpleRouterApp).mount('#app')
What other ways can I try so render() can return a Component dynamically?
You could use async-components :
import {createApp, h,defineAsyncComponent} from 'vue'
....
render () {
const matchingPage = routes[this.currentRoute] || '404'
const ViewComponent= defineAsyncComponent(
() =>import(`./pages/${matchingPage}.vue`)
)
return h(ViewComponent)
},
Related
Below is the code located at "Pages/home.js". // localhost:3000/home
import axios from 'axios';
import Section1 from '../components/home-sections/section-1';
const Homepage = ({ show }) => {
const Html = JSON.parse(show.response.DesktopHTML);
const renderSection = () => {
return Html.map((itemData,index)=>{
return(<div key={index}>{itemData.DisplayName}</div>)
})
}
return(
<div>
{ renderSection()}
<Section1 />
</div>
)
}
export const getServerSideProps = async ({ query }) => {
try {
const response = await axios.get(
`https://api.example.com/getHomeSection?title=Section 1`
);
return {
props: {
show: response.data,
},
};
} catch (error) {
return {
props: {
error: error.error,
},
};
}
};
export default Homepage;
Now same code I added into section-1.js and this file is located to "components/home-sections/section-1.js"
Now getServerSideProps is working fine in home.js, but in section-1.js it is not working.
Error: TypeError: show is undefined in section-1.js
You cannot use getServerSideProps in non-page components. You can either pass the prop from Home to HomeSection or create a context so the value can be available globally from the component tree
getServerSideProps can only be exported from a page. You can’t export
it from non-page files.
https://nextjs.org/docs/basic-features/data-fetching#only-allowed-in-a-page-2
getServerSideProps can only be exported from Page components. It will not be run on components imported into a page.
However, you could export a function from the component that returns the props, and call that function from the page's getServerSideProps function.
Create a getServerSideProps function on the component.
// #components/MyComponent.tsx
import { GetServerSidePropsContext } from 'next';
function MyComponent(props: IMyComponentProps) {
return (<div>MyComponent</div>;)
}
MyComponent.getServerSideProps = async (context: GetServerSidePropsContext): Promise<{ props: IMyComponentProps }> => {
return { props: { ... } };
}
export default MyComponent;
In your page's getServerSideProps function, call the component's getServerSideProps function and merge the props from the component with the props from the page.
// mypage.tsx
import MyComponent from '#components/MyComponent';
const Page: NextPageWithLayout = (props: IIndexPageProps) => {
return <MyComponent />;
}
export async function getServerSideProps(context: GetServerSidePropsContext): Promise<{ props: IIndexPageProps }> {
let componentServerSideProps = await MyComponent.getServerSideProps(context);
let otherServerSideProps = { props: { ... } };
return {
props: {
...componentServerSideProps.props,
...otherServerSideProps.props
}
};
}
i use apollo client and react in project
i want appear loading indicator while network request, so i set react variables and change it inside apollo link
but it cause cannot update component(Indicator) while rendering a diffrend component(component that call useQuery hook)
loadingLink.ts
import { ApolloLink } from '#apollo/client';
import { loadingVar } from 'gql/store/reactiveVariables';
export const loadingLink = new ApolloLink((operation, forward) => {
loadingVar(true);
return forward(operation).map(data => {
loadingVar(false);
return data;
});
});
loadingIndicator.ts
import React from 'react';
import { useReactiveVar } from '#apollo/client';
import { loadingVar } from 'gql/store/reactiveVariables';
import { Indicator } from './Indicator';
const LoadingIndicator: React.FC = () => {
const loading = useReactiveVar(loadingVar);
if (!loading) return null;
return <Indicator />;
};
export default LoadingIndicator;
error message
error message
BatchList.tsx
const BatchList = () => {
const {data, error} = useQuery(~~~);
if(error) return null;
if(loading || !data) return null;
return ~~~~
}
in documentation, they say should use useEffect hook but inside ApolloLink i can't use useEffect hook
How can i fix it
Scroll.js
import React from "react";
export const ScrollToTop = ({ children, location }) => {
React.useEffect(() => window.scrollTo(0, 0), [location.pathname]);
return children;
};
Scroll.test.js
import React from "react";
import { ScrollToTop } from "./ScrollToTop";
describe("ScrollToTop", () => {
it("", () => {
expect(
ScrollToTop({
children: "some children",
location: { pathname: "the path" }
})
).toEqual();
});
});
and the result I'm getting is
enter image description here
You should not call ScrollToTop as a function directly, this is what error message is complaining about.
React docs recommend the Testing Library for writing tests.
Here is an example of how you can write Scroll.test.js using the library above:
import React from "react";
import { render } from '#testing-library/react';
import { ScrollToTop } from "./ScrollToTop";
describe("ScrollToTop", () => {
it('calls window.scrollTo()', () => {
window.scrollTo = jest.fn(); // create a moack function and record all calls
render(<ScrollToTop location={{ pathname: 'pathname' }}>Text</ScrollToTop>); // render a component
expect(window.scrollTo).toHaveBeenCalledWith(0, 0); // check that scrollTo mock was called
});
});
I got an article showing how to pass a component as a prop, but I could not make it works, can anyone help me on it?
This is the example I got.
import React from "react";
import Foo from "./components/Foo";
import Bar from "./components/Bar";
const Components = {
foo: Foo,
bar: Bar
};
export default block => {
// component does exist
if (typeof Components[block.component] !== "undefined") {
return React.createElement(Components[block.component], {
key: block._uid,
block: block
});
}
}
And this is my code
I have one file called routes.js, that has the state called routes.
var routes = [
{
path: "/user-profile",
name: "Quem Somos",
icon: "FaIdBadge",
component: UserProfile,
layout: "/admin"
}
And another component called Sidebar, where I receive routes and need to change the icon based in what is configured at the 'routes' prop.
const Components = {
fa:FaIdBadge
}
<i>{prop => Components(prop.icon)}</i>
But the property with the icon is not recognized.
You're pretty close.
Choosing the Type as Runtime
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
// Correct! JSX type can be a capitalized variable.
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}
So more specific to your example
// component map in the file for lookup
const components = {
fa: FaIdBadge,
}
...
// In the render function
// fetch the component, i.e. props.icon === 'fa'
const IconComponent = components[props.icon];
...
<IconComponent />
So I'm trying recoilJS for a js game that I am building and it pretty neat, but the need to update atoms from components only feels like a limitation.
To create a game loop, I put all the logic on empty component so I will be able to read and write states. Even if I will construct the login outside of the component, I will need especially move different stats around all the time. There is a way to update atoms outside of react component (not via hooks)?
I use RXJS to help to set RecoilJS value outside of the component.
At the start, I created 4 parts as
Main component
RecoilJS component
Atom file
set RecoilJS outside value of the component file
1).Main
import React from 'react';
import {
RecoilRoot
} from 'recoil';
function App() {
return (
<RecoilRoot>
<MainScreens />
<RecoilJSComponent/>
</RecoilRoot>
);
}
2).RecoilJS component
import React from 'react';
import {
useRecoilCallback
} from 'recoil';
import { Subject } from 'rxjs';
export const setRecoil = new Subject();
const getRecoil = new Subject();
const returnRecoil = new Subject();
export const promiseGetRecoil = (recoilObj) => {
return new Promise(async (resolve, reject) => {
getRecoil.next(recoilObj)
returnRecoil.subscribe({
next: (value) => {
if (recoilObj === value.recoilObj) {
resolve(value.value)
}
}
});
})
}
export default function RecoilJSComponent() {
const setStore = useRecoilCallback(({ set }) => (n) => {
set(n.recoilObj, () => (n.value));
}, [])
const getStore = useRecoilCallback(({ snapshot }) => async (recoilObj) => {
const valueRecoilObj = await snapshot.getPromise(recoilObj);
returnRecoil.next({ recoilObj: recoilObj, value: valueRecoilObj })
}, [])
setRecoil.subscribe({
next: (value) => {
setStore(value)
}
});
getRecoil.subscribe({
next: (recoilObj) => {
getStore(recoilObj)
}
});
return null;
}
3).Atom file
export const textState = atom({
key: 'textState'
default: ''
});
4).set RecoilJS outside the value of the component file
import API from './Api';
import { setRecoil } from './RecoilJSComponent'
import { textState } from './textState'
export const setValueReCoil = () => {
API()
.then(result => {
setRecoil({ recoilObj: textState, value: result })
})
.catch(ex => {
})
};
The main idol is in 2 and 4
In number 2,
I create to use RXJS for setting value via the component and I export RXJS to set a value on RecoilJS outside of the component
I hope my idol can help you to resolve your problem
There isn't right now. Opened a suggestion for recoil team.