How to initialize router before rendering anything in Nextjs? - next.js

I'm using react-query, when I get the id from the url and try to call it inside getSubject, it passes an undefined value http://localhost:3000/api/subject/undefined
but when I click a link from another component to get in this subject component it works but if refresh the page it does not work.
const router = useRouter()
const { id } = router.query
const { data } = useQuery('subjects', async () => await getSubject(id))
return value...
}

You should use getServerSideProps in this case. It has access to query params. On top of that you can prefetch data on the server side too.
export interface PageProps {
id: string;
}
export function Page({ id }: PageProps ) {
const { data } = useQuery('subjects', async () => await getSubject(id))
}
export const getServerSideProps: GetServerSideProps<PageProps > = async ({
params,
}) => {
const { id } = params;
return {
props: {
id,
},
};
};
If you still want to use router, you can wait for router.isReady flag. When it is true, query params should be parsed.

Related

NextJs: getServerSideProps is not working with Apollo: fetch failed

I'm trying to generate the page from the server side page on Next.js, But I'm having a problem with it, so I have created an Apollo instance and I'm importing a Query from my queries, and I pass the variable as I do on useQuery from apollo on the client, because I don't know another way to do that, also how to handle errors on this?
Here are my getServerSideProps:
export async function getServerSideProps(context) {
const slug = context.params.slug;
const data = await Static.query({
query: LANDING,
variables: { slug },
});
return {
props: {
data: data,
},
};
}
Here is my query:
import gql from "graphql-tag";
export const CATEGORIES = gql`
query CategoriesView {
CategoriesView {
_id
Name
Description
Icon
}
}
`;
Here is my Client:
import {
ApolloClient,
HttpLink,
ApolloLink,
InMemoryCache,
} from "#apollo/client";
const uri = "http://localhost:3000/api"
const httpLink = new HttpLink({uri});
export const Apollo = new ApolloClient({
ssr: typeof window === "undefined" ? true : false,
cache: new InMemoryCache(),
link: ApolloLink.from([httpLink]),
});
But I get this error: failed to fetch
Here is a screenshot of it:
Here is my example, working in my case.
import { useSubscription, useQuery, gql } from "#apollo/client";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
//your query here ; first check if your query works (use your playground)
const QUERY = gql`
query {
customers{
data{
attributes{
firstname
lastname
location
phone
createdAt
}
}
}
}
`;
const Page = () => {
//apollo function
const { data, loading, error } = useQuery(QUERY);
if (loading) return <div>Loading...</div>
if (error) return <div>Failed to load!</div>
return (
<>
{JSON.stringify(data)}
</>
)
};
//can do with staticProps, serverProps, etc. Below just an example - delete if not needed
export async function getStaticProps({ locale }) {
return {
props: {
...(await serverSideTranslations(locale, ["common"])),
},
};
}
export default Page;
I am not sure if you can put gql query in getServerSideProps because apollo creates some sort of "cache" for your queries.
And check #apollo/client library

Next.js, I want to check store in getServerSideProps() query. how can I do that

I'm using nextjs 13, just started. I'm using getServerSideProps() but the request is rethrown every time it comes to the page. I want to check my Store field first, if the store field is empty, then it should send a request. how can I do it.
// current
export const getServerSideProps = async () => {
const { data } = await axios.get(`https://www.freetogame.com/api/games`);
return { props: { data: data } };
};
// i want
export const getServerSideProps = async () => {
if(store.gamesState.length <0 ){
const { data } = await axios.get(`https://www.freetogame.com/api/games`);
dispatch(gamesActions.setGames(data))
}
};

Apollo client can't query in Nextjs getServerSideProps via SchemaLink

Apollo client fails to do query when initialized with SchemaLink (nexus) instead of HttpLink. I get this error Cannot set properties of undefined (setting 'select')
function createIsomorphLink() {
if (typeof window === 'undefined') {
const { SchemaLink } = require('#apollo/client/link/schema')
const { schema } = require('./nexusSchema')
return new SchemaLink({ schema })
} else {
const { HttpLink } = require('#apollo/client/link/http')
return new HttpLink({
uri: '/api/graphql',
credentials: 'same-origin',
})
}
}
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: from([errorLink, createIsomorphLink()]),
cache: new InMemoryCache(),
})
}
Here's my getServerSideProps. I initialize apollo client and use apolloClient.query(...)
export const getServerSideProps = async ({ params }) => {
const id = params.id
const apolloClient = initializeApollo()
// Here's where the error occurs
const { data } = await apolloClient.query({
query: gql`
query findUniquePage($id: String!) {
findUniquePage(where: { id: $id }) {
title
type
content
isPublished
}
}
`,
variables: { id },
})
// ...snippet..
}
I tried creating simple 'hello' query with string response, so that there was no select part. But error stayed the same.
export const getServerSideProps = async () => {
const apolloClient = initializeApollo()
const { data } = await apolloClient.query({
query: gql`query hello { hello }`,
})
return {
props: {},
}
}
My apollo client version is 3.7.0. The latest is 3.7.1 but by CHANGELOG there seems to be nothing that addresses my issue. Probably, the problem is how apollo client requests my api via SchemaLink, or how my api parses that request (apollo server + code first nexus). Because when I replaced SchemaLink with HttpLink, code worked fine. But I kinda want to keep the SchemaLink. Any advice?

next-redux-wrapper: after hydration useSelector returns initial value (null), but getServerSideProps passes the correct value to the page

I got getServerSideProps like this, which gets token from cookie and gets uses it to fetch user data with RTKQ endpoint. Then dispatches that data to authSlice.
So far it's good.
const getServerSideProps = wrapper.getServerSideProps(
(store) =>
async ({ req, res }: GetServerSidePropsContext) => {
let result: AuthState = null;
const data = getCookie('device_access_token', { req, res });
if (data?.toString()) {
result = await store
.dispatch(
usersApi.endpoints.getUserByToken.initiate(data?.toString())
)
.unwrap();
}
if (result) store.dispatch(setUser(result));
return { props: { auth: result } };
}
);
Then I merge this auth data in the store like this:
const reducer = (state: ReturnType<typeof rootReducer>, action: AnyAction) => {
if (action.type === HYDRATE) {
console.log('payload#HYDRATE', action.payload);
const nextState = {
...state, // use previous state
...action.payload, // apply delta from hydration
};
if (state.auth.user) {
nextState.auth.user = state.auth.user;
nextState.auth.token = state.auth.token;
} // preserve auth value on client side navigation
return nextState;
} else {
return rootReducer(state, action);
}
};
console.log('payload#HYDRATE', action.payload); also shows correct data.
The problem is in a page where I export getServerSideProps,
const IndexPage: NextPage = ({ auth }: any) => {
console.log('user#index', auth);
console.log('userSelect#index', useSelector(selectCurrentUser));
return auth ? <Home /> : <NoAuthHome />;
};
auth shows correct value, but useSelector(selectCurrentUser) shows null
Can someone tell me if this is how it is intended to be, or I'm doing something wrong?
Because I don't want prop-drilling auth on countless pages, just use useSelector(selectCurrentUser) wherever necessary.
Finally found the problem!
problem was in _app.tsx
I wrapped <Component {...pageProps} /> with <Provider store={store} at the same time exporting with wrapper.withRedux(MyApp)

Object data null sms still sent twilio authy

Im trying to implement the authy-node phone verification with firebase functions and my app in react-native the message is sent to the correct mobile phone but for some reason the data I get back from the api is null any ideas out there
My Api firebase functions
import * as functions from 'firebase-functions';
const authy = require('authy')('mySecret');
export const getCode = functions.https.onCall((data, context) => {
const {
number, countryCode
} = data;
return authy.phones().verification_start(number, countryCode, { via:
'sms', locale: 'en', code_length: '4' }, (err: any, res: any) => {
if (err) {
throw new functions.https.HttpsError(err);
}
return res;
});
});
and this is my call from my app
export default class test extends Component {
constructor() {
super();
}
componentWillMount() {
const getCode = firebase.functions().httpsCallable('getCode');
getCode({number: 'theCorrectNumber', countryCode: '44'})
.then(function (result) {
const data = result;
console.log(data)
}).catch( function (error){
console.log(error)
})
}
render() {
return (
<View/>
);
}
}
Twilio developer evangelist here.
From what I can see in the Authy Node library that I'm assuming you're using, making a request to the API does not return a Promise. Instead it is built with request and responds to asynchronous requests using callbacks only. You do deal with the callback, but you are returning the result of calling the asynchronous function, which is null, rather than the result from the callback.
Perhaps including a callback as part of the function call would work better:
import * as functions from 'firebase-functions';
const authy = require('authy')('mySecret');
export const getCode = functions.https.onCall((data, callback) => {
const { number, countryCode } = data;
return authy
.phones()
.verification_start(
number,
countryCode,
{ via: 'sms', locale: 'en', code_length: '4' },
callback
);
});
You can then use it like this:
export default class test extends Component {
constructor() {
super();
}
componentWillMount() {
const getCode = firebase.functions().httpsCallable('getCode');
getCode({ number: 'theCorrectNumber', countryCode: '44' }, (err, res) => {
if (err) {
throw new functions.https.HttpsError(err);
}
const data = res;
console.log(data);
});
}
render() {
return <View />;
}
}
Let me know if that helps at all.

Resources