I'm trying to use the #segment/consent-manager for a Next.js 13 project, but running into problems. I've tried to using this Next.js example in the documentation in my code, but nothing seems to work and I keep getting this error:
Server Error TypeError: Object prototype may only be an Object or null: undefined This error happened while generating the page. Any console logs will be displayed in the terminal window.
The standalone script works if I put it in the Head and use Script elements like this:
import Script from "next/script";
import * as snippet from "#segment/snippet";
export default function Head() {
const loadSegment = () => {
const options = {
apiKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY,
page: true,
load: true,
};
return snippet.min(options);
};
return (
<>
<title></title>
<meta content="width=device-width, initial-scale=1" name="viewport" />
<link rel="icon" href="/favicon.ico" />
<Script
dangerouslySetInnerHTML={{ __html: loadSegment() }}
id="segmentScript"
/>
<Script
id="consentManagerScript"
dangerouslySetInnerHTML={{
__html: `window.consentManagerConfig = function(exports) {
var React = exports.React
var inEU = exports.inEU
var bannerContent = React.createElement(
'span',
null,
'We use cookies (and other similar technologies) to collect data to improve your experience on our site. By using our website, you՚re agreeing to the collection of data as described in our',
' ',
React.createElement(
'a',
{ href: '/docs/legal/website-data-collection-policy/', target: '_blank' },
'Website Data Collection Policy'
),
'.'
)
var bannerSubContent = 'You can change your preferences at any time.'
var preferencesDialogTitle = 'Website Data Collection Preferences'
var preferencesDialogContent =
'We use data collected by cookies and JavaScript libraries to improve your browsing experience, analyze site traffic, deliver personalized advertisements, and increase the overall performance of our site.'
var cancelDialogTitle = 'Are you sure you want to cancel?'
var cancelDialogContent =
'Your preferences have not been saved. By continuing to use our website, you՚re agreeing to our Website Data Collection Policy.'
return {
container: '#target-container',
writeKey: '${process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY}',
shouldRequireConsent: inEU,
bannerContent: bannerContent,
bannerSubContent: bannerSubContent,
preferencesDialogTitle: preferencesDialogTitle,
preferencesDialogContent: preferencesDialogContent,
cancelDialogTitle: cancelDialogTitle,
cancelDialogContent: cancelDialogContent
}
}`,
}}
/>
<Script src="https://unpkg.com/#segment/consent-manager#5.3.0/standalone/consent-manager.js" />
</>
);
}
I'm able to proceed with my project using the standalone script, but I feel there might be an issue with using the ConsentManager component in Next 13. Has anyone else had any issues with this? Or does anyone have any solutions that I haven't seen? I'd prefer to use the ConsentManager component if I can.
Version = "next": "13.1.1",
Related
I am building a NextJS blogging site which uses #expo/next-adapter . This site has two pages. One is the user page and the other one is post page. The user page has getServerSideProps implemented to fetch data from Firebase. There is next/link's <Link /> implemented on the post page which points to /user/[uid].
Now the problem is if I navigate to user from post using the <Link /> Everything works ok but if I refresh the page the page becomes unresponsive and all the styling related client side JS does not run.
PS : SSR is not implemented on the post page. Please forgive me if this is a rookie mistake because I am one.
PS #2 : This project is hosted on Firebase and uses a cloud function to handle SSR. The above problem does not show up if I run the production build locally using next build && next start
Thank you in advance...
Edit #1 :
This error shows up on the browser console when I either try to manually go to /user/[uid] or refresh the page after navigating back from post
main-590e886005382c6f8e8a.js:1 Uncaught TypeError: Cannot read property 'map' of undefined
at DqTX.t.default (main-590e886005382c6f8e8a.js:1)
at Object.IKlv (main-590e886005382c6f8e8a.js:1)
at l (webpack-288ceb4b356766e18474.js:1)
at Object.BMP1 (main-590e886005382c6f8e8a.js:1)
at l (webpack-288ceb4b356766e18474.js:1)
at t (webpack-288ceb4b356766e18474.js:1)
at Array.r [as push] (webpack-288ceb4b356766e18474.js:1)
at 0c947092cfe8a35964e0670062fe3410218106ea.62154c5756c292e8972d.js:1
Edit #2: Code for the function [user].js
export async function getServerSideProps(context) {
if(admin.apps.length == 0){
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
storageBucket: '*************.appspot.com',
});
}
try {
const fireStore = admin.firestore();
const userDataRef = await fireStore.collection('users').where('uid', '==', `${context.query.user}`).get();
const postDataRef = await fireStore.collection('posts').where('uid', '==', `${context.query.user}`).get();
let userData;
let postData = [];
if(!userDataRef.empty){
if(userDataRef.docs[0].exists){
userData = userDataRef.docs[0].data()
}
if(!postDataRef.empty){
for(let post of postDataRef.docs){
const thumbImage = await admin.storage().bucket().file(`postData/${post.id}/${post.data().thumb}`).publicUrl();
deckData.push(JSON.parse(JSON.stringify({...post.data(), id: post.id, thumb: thumbImage})));
}
}
}
return {
props: {user: JSON.parse(JSON.stringify(userData)), posts: [...postData]}, // will be passed to the page component as props
}
} catch(e) {
return {
props: {user: 'error', posts: []},
}
}
}
I am getting this error in Next.js:
Error: The provided 'href' (/subject/[subject]) value is missing query values (subject) to be interpolated properly. Read more: https://err.sh/vercel/next.js/href-interpolation-failed`.
I have a dynamic page set up as /subject/[subject].tsx. Now in my navigation I have:
<Link href={'/subject/${subject}'} passHref><a>{subject}</a></Link>
It works fine when I access the page with different paths but when I am pressing on a button on the page it throws the error above which I imagine is because the component rerenders. If you go to the page in the error it says: Note: this error will only show when the next/link component is clicked not when only rendered.
I have tried to look for a solution and I tried doing:
<Link href={{pathname: '/subject/[subject]', query: {subject: subject}}}></Link>
but nothing changed. I read the docs and it seems that the as prop is only an optional decorator that is not used anymore so I fail to see how that can help me.
I got the same issue when trying to redirect user to locale. I did it in useEffect. After investigate I discovered that on first render router.query is empty, so it's missing required field id. I fix it by using router.isReady
export const useUserLanguageRoute = () => {
const router = useRouter()
useEffect(() => {
const {
locales = [],
locale,
asPath,
defaultLocale,
pathname,
query,
isReady // here it is
} = router
const browserLanguage = window.navigator.language.slice(0, 2)
const shouldChangeLocale =
isReady && // and here I use it
locale !== browserLanguage
&& locale === defaultLocale
&& locales.includes(browserLanguage)
if (shouldChangeLocale) {
router.push(
{
pathname,
query,
},
asPath,
{ locale: browserLanguage }
)
}
}, [router])
}
Another possible solution could be redirect using the router.push function:
const myRedirectFunction = function () {
if (typeof window !== 'undefined') {
router.push({
pathname: router.pathname,
query: {...router.query, myqueryparam: 'myvalue'},
})
}
}
return (
<>
<button onClick={() => {myRedirectFunction()}}> Continue </button>
</>
)
It is important to include ...router.query because there is where the [dynamic] current value is included, so we need to keep it.
Reference: https://github.com/vercel/next.js/blob/master/errors/href-interpolation-failed.md
You better do a null || undefined check in prior.
#Bentasy, Like you rightly pointed out, any re-render of the page is expecting you to pass in the dynamic route params again. The way I avoided page re-rendering with subsequent clicks on the page was to replace Link tag on the page with a label tag. I was using the Next Link tag to navigate between the tabs on this image which generated this same error. So I replaced the Link tags with label tags and the error was solved.
I was having the same problem, this is how I solved it.
While pushing something to the router, we need to give the old values in it.
In that:
const router = useRouter()
router.push({
...router,
pathname: '/your-pathname'
})
try add this function, it work for me:
export async function getServerSideProps(context) {
return {
props: {},
};
}
I have one query and one subscription, what I am trying to do is add my data to previous query so that it shows the full list.
I have one query which is returning me list of students and I am rendering that on UI like below
function Test(props) {
const { loading, data: dta } = useQuery(GETSTUDENTS);
const { data: d } = useSubscription(GETSUBSTUDENTS, {
onSubscriptionData: ({ subscriptionData: { data } }) => {
let fname = data.getSubStudent.fname;
let lname = data.getSubStudent.lname;
dta.getStudents.push({ fname, lname });
},
});
return (
<div className="">
{dta &&
dta.getStudents.map((li) => {
<div>
<p>{li.fname}</p>
<p>{li.lname}</p>
</div>;
})}
</div>
);
}
export default Test;
But the main issue is the above one is not updating the cache so when I change the routes and come bqack again it takes the previous data only.
So What I wnat to know na what is the best way to do this, I have check subscribeToMore also but did not get idea How to implement that and how it works with hooks.
I am getting some data from subscription and on that basis I want to change some other part so can I use refetchQueries I did not found any good tutorial which uses hooks (react-apollo-hooks) using qraphql
First, you can just use the pooling option of the useQuery instead of subscription,
I suggest you check it.
From Apollo docs:
"In the majority of cases, your client should not use subscriptions to
stay up to date with your backend. Instead, you should poll
intermittently with queries, or re-execute queries on demand when a
user performs a relevant action."
Apollo subscription
If you still want to use the subscription I think you should use the subscribeToMore and to update your cache policy inside the apollo cache file:
const cache = new InMemoryCache({
typePolicies: {
Agenda: {
fields: {
tasks: {
merge(existing = [], incoming: any[]) {
return [...existing, ...incoming];
},
},
},
},
},
});
You can read more about it here: merge cahce
And check that video: youtube apollo cache
I have created an education application with electron-vue js and now I have decided to implement Google Analytics in this desktop application. I have googled for some packages but could not find what exactly I can get from Google Analytics i.e., what features of google analytics I should use to improve my study-based desktop application( electron-vue js platform).
Here is a little bit description about it:
a) the application is totally offline.
b) it includes study stuff like audios,videos,etc.,.
c) it also provides features like printing study material.
Even a single idea can help me figuring out what to do with Google analytics and can be a good head start.
Thanking you in advance!
Google analytics will consider Electron a website.
I use this plugin https://github.com/MatteoGabriele/vue-analytics
And set it up like this in your main entry for Vue in your renderer
import VueAnalytics, { set } from 'vue-analytics'
Vue.use(VueAnalytics, {
id: 'UA-idnumber',
router,
// debug: {
// enabled: true,
// trace: true // help you find problems
// },
fields: {
cookieDomain: 'none' // no domain
},
autoTracking: {
pageviewTemplate (route) {
// allow custom page titles in the router meta
let title = route.meta.title
if (!title) {
title = route.name
}
return {
page: route.name,
title: title,
location: route.path
}
}
}
})
set('allowAdFeatures', false) // no ads
set('checkProtocolTask', null) // ignore electron protocols
set('checkStorageTask', null) // ignore electrons cache solution, assume it works
Then I have directives like this
import { event } from 'vue-analytics'
Vue.directive('gaClick',
{
inserted: (el, binding, vnode) => {
let routeName = vnode.context.$route.meta.title
if (!routeName) {
routeName = vnode.context.$route.name
}
el.addEventListener('click', async e => {
const category = binding.value && binding.value.category ? binding.value.category : 'button Click'
const action = binding.value && binding.value.action ? binding.value.action : 'Click'
const label = binding.value && binding.value.label ? binding.value.label : `${e.target.innerText} (${routeName})`
const value = binding.value && binding.value.value ? binding.value.value : 0
event(category, action, label, value)
})
}
})
To be used on buttons and links like this
<router-link
:to="{name:'status-page'}}"
v-ga-click="{label:'Status Page'}"
>
Status Page
</router-link>
This will give you nearly all the features google analytics has. Unless they decide to change things again and break it. Like they did in their push to firebase analytics for "apps"
I'm trying to create a simple web app with authentication via Telegram. Telegram has it's own widget with callback which returns you user data after logging in. And the problem is in the script attribute "data-onauth" here you pass the callback you want to execute after success auth.
( https://core.telegram.org/widgets/login - widget documentation if you need it )
To locate log in button in the place you want you just need to paste script given by Telegram's widget generator, but since I can't paste script tag in components template ( vue just won't compile it & just return you error ) I chose to create script element add needed attributes and append it in mounted().
Here is my component code
<template>
<header>
<div class="auth" id="telegramAuth">
</div>
</header>
</template>
<script>
export default {
name: "Header",
data: () => ({}),
mounted() {
let telegramAuth = document.createElement("script");
telegramAuth.setAttribute("async", "");
telegramAuth.setAttribute(
"src",
"https://telegram.org/js/telegram-widget.js?7"
);
telegramAuth.setAttribute("data-userpic", "false");
telegramAuth.setAttribute("data-telegram-login", "t_adv_bot");
telegramAuth.setAttribute("data-size", "large");
telegramAuth.setAttribute("data-onauth", this.loginWithTelegram);
telegramAuth.setAttribute("data-request-access", "write");
document.querySelector("#telegramAuth").appendChild(telegramAuth);
},
methods: {
loginWithTelegram: function onTelegramAuth(user) {
console.log(user);
}
}
};
</script>
But when I try to do so I get Uncaught SyntaxError: Function statements require a function name.
And I don't know how to solve it. Thanks in advance and sorry for my poor English
methods: {
loginWithTelegram(user) {
console.log(user);
}
}