Vue3 Composition API Provide/Inject to Router's index.js - vuejs3

I am using a third-party plugin called Lenis for smooth scrolling on my Vue app. I decided to add it to my main.js and utilize "provide". I am using "inject" in components where I can start and stop the scroll smoothing. It works as expected.
What I want to do is to be able to do this in my router's index.js so I can use scrollBehavior().
From this:
return new Promise((resolve, reject) => {
resolve({left: 0, top: 0});
});
To this:
return new Promise((resolve, reject) => {
// lenis.scrollTo("#anchor");
});
When I inject it into my router's index.js, I get undefined for my variable. What's the workaround for this? Any suggestions?
Thank you.

Related

Next.js with Firebase Remote Config

I was trying to integrate Google's Firebase Remote config into my Next.js app.
When following Firebase's docs, and just inserted the functions directly into my component's code block, like so:
const remoteConfig = getRemoteConfig(app);
I keep getting the following error when following their documentation:
FirebaseError: Remote Config: Undefined window object. This SDK only supports usage in a browser environment.
I understand that it happens since Nextjs is rendered server-side, so there's no window object yet, so here's my solution:
import {
fetchAndActivate,
getRemoteConfig,
getString,
} from 'firebase/remote-config';
const Home: NextPage<Props> = (props) => {
const [title, setTitle] = useState<string | null>('Is It True?');
useEffect(() => {
if (typeof window !== 'undefined') {
const remoteConfig = getRemoteConfig(app);
remoteConfig.settings.minimumFetchIntervalMillis = 3600000;
fetchAndActivate(remoteConfig)
.then(() => {
const titleData = getString(remoteConfig, 'trueOrFalse');
setTitle(titleData);
})
.catch((err) => {
console.log(err);
});
}
});
return <h1>{title}</h1>}
Basically, the important part is the if statement that checks if the window object exists, then it execute the Remote Config functions according to Firebase documents.
Also, it worked outside a useEffect, but I think that's probably a bad idea to leave it outside, maybe even it should have a dependency, can't think of one at the moment.

Use tw elements in a NextJS project

I'm trying to use tw-elements in a nodejs project. If I follow their documentation and just import tw-elements in my _app, I get this error:
ReferenceError: document is not defined
I found a stackoverflow response that said to put this at the start of the index.min.js file of tw-elements:
if (typeof window == "undefined")return;
I did and the error disappeared, but the library still won't work. Any ideas?
First, add Tailwind Elements using these NPM steps here.
Here is how to get it to work with Nextjs:
First step is to add this code to your _app.js file:
useEffect(() => {
const use = async () => {
(await import('tw-elements')).default;
};
use();
}, []);
Like this for example:
export default function App({ Component, pageProps }) {
useEffect(() => {
const use = async () => {
(await import('tw-elements')).default;
};
use();
}, []);
return (
Make sure you add import { useEffect } from "react"; to the top of _app.js.
It’s also important that you’re not importing Tailwind Elements anywhere else expect for the _app.js file.
Tailwind Elements should now be working!
I was facing the same issue. I followed Tyrell Curry's answer but It encountered type not found error because I was using typescript.
Unfortunately the type definitions were missing for tailwind-elements library.
I made a little change it the function so that type check have to be avoided by using as any.
useEffect(() => {
const use = async () => {
(await import("tw-elements" as any)).default;
};
use();
}, []);

Caching into subcomponents

I'm building a site in nextjs but I came across a problem.
I have the cover of the site, where there is a list of products, and on the top menu the list of product categories.
The products are looking via getStaticProps (So that it is done by the servideor and is cached).
However, the categories are inside a separate component, where inside I need to load the category listing from my API.
getStaticProps does not work in this case as it is not a page but a component.
Fetching inside a useEffect is bad, as each access loads the api.
So the question remains, how can I do this server-side fetch and deliver the cached (json) return? (Simulating getStaticProps)
As your component is listed on every page, you could consider either using Context or local caching in the browser within the shared Category component.
Context provides a way to pass data through the component tree without
having to pass props down manually at every level.
But there are performance considerations using Context and may be overkill here. If you really don't want to hit the API, data is not changing often, and you don't need to pass functions through the component tree, then you could consider some basic browser caching using localStorage.
import React, { useState, useEffect } from 'react';
const mockAPI = () => {
return new Promise((resolve) => {
setTimeout(() => {
return resolve([
{
id: '1',
name: 'One'
},
{
id: '2',
name: 'Two'
}
]);
}, 1000);
});
};
const Component = () => {
const [categories, setCategories] = useState(null);
useEffect(() => {
(async () => {
if (categories === null) {
let data = window.localStorage.getItem('categories');
if (data === null) {
console.info('calling api...');
data = await mockAPI();
window.localStorage.setItem('categories', JSON.stringify(data));
}
setCategories(JSON.parse(data));
}
})();
}, []);
return <nav>{categories && categories.map((category) => <li key={category.id}>{category.name}</li>)}</nav>;
};
export default Component;
The caveat here is you need to know where to clear localStorage. There are many ways to implement this from using basic timers to looking at SWR
You could also consider Redux but is probably overkill for something elementary like this.

Firebase .on with Vue without using Vuefire

I'm trying to implement a real-time connection with Firebase's .on ref, but have no idea where to plug that in or use it in Vue. The tutorials online all use Vuefire to accomplish it, but if I just want to use the Firebase SDK, where can I activate this .on connection in my Vue project and have it work in a two-way data connection real-time?
Hmm.. It didn't seem to work.
This is what I'm using,
export default {
name: 'index',
data() {
return {
id: '1234',
meData: 'test'
}
},
mounted() {
const database = firebase.database().ref( 'rooms' + this.id );
database.on( 'value', snapshot => {
this.meData = snapshot.val();
});
}
}
I tried testing with push, it works, so the config and firebase is working, but the .on doesn't seem to work. I get no errors too so I'm having a hard time figuring out the issue. =(
At first, always the best option is to use VueFire if you need to use Vue.js and Firebase.
However, if you want to use Vue.js without Vuefire, you can set up the firebase instance in mounted section in your component. Vue component's lifecycle is not the same as the one without Vue, so you better to use lifecycle handler provided by Vue.
Vue.component("YourComponent", {
...
mounted() {
firebase.initializeApp({
apiKey: "apiKey",,
databaseURL: "https://databaseName.firebaseio.com"
});
const database = firebase.database();
database.ref('/users/100').once('value').then((snapshot) => {
// Do your business
});
...
//
// You can also set up more handlers like above...
//
},
...
});
However, if you want to use two-way binding, it is a little tough. The good point of Vuefire is its easy mixin of Vue component data structure and Firebase instance.
Without Vuefire, the code I can think up would be like this
Vue.component("YourComponent", {
...
data() {
return {
users: []
};
},
...
mounted() {
//
// Initialize Firebase SDK and get `database` to use below.
//
...
database.ref('/users').on('value', (snapshot) => {
// By using arrow function, the context of `this` here is binded
// into the current component data `users`.
this.users = snapshot.val();
});
},
...
});
In case anyone else is looking to use Firebase in Vue without Vuefire.
Do check out this video!
Vue 2 & Vuex & Firebase Tutorial - Getting It All Working Together
https://youtu.be/niPgyv53x8c

How to navigate at the end of a Redux action?

I want to use only React, React Redux, React Router and Redux Thunk.
I want to navigate to a dashboard page when a successful user creation action is dispatched. Here is my async action creator,
export function createUser() {
return dispatch => {
dispatch(creatingUser());
return axios.post('/api/users').then(() => {
// how to navigate to dashboard after this action is dispatched?
dispatch(createdUser());
});
};
}
Can you show me exactly where is the place I should naviage programmatically?
Initially looking, I would hope that "createdUser" returns a promise (like #idbehold asked previously)
in a nutshell, something like this.
// make sure your function createdUser returns a promise
function createdUser() {
return new Promise((resolve, reject) => {
//simulate some api request
setTimeout( () =>{
// api resolves. in the .then() do:
resolve()
}, 4000)
})
}
// the dispatch will forward resolution of the promise ahead into the
// .then.. then you can redirect.
dispatch(createdUser()).then( ()=> {
console.log("NAVIGATING AWAY")
//browserHistory.push('/some/path')
//assuming you are importing browserHistory
})
I hope I was helpful, if not :-( , perhaps I didn't fully understand what your need is/was. Let me know, and I'll try to help further.

Resources