Send param to fetch in getInitialProps react and nextjs - reactjs

I 'm traying to send a param to getInitialProp function to made the fecth to the correct json.
here is my code:
hepler.js --> here I made the fetch per se.
export async function getEvents() {
const res = await fetch("https://url/eventos.json");
let new_data = await res.json();
return { events: new_data.data };
}
export async function getDetails(slug) {
const res = await fetch(`https://myurl/${slug}.json`);
let data_detail_event = await res.json();
return { data_detail_event };
}
_app.js // here I have the getInitialProps and works great
import App from "next/app";
import ContextProvider from "../provider/ContextProvider";
import fetch from "isomorphic-unfetch";
import {getEvents, getDetails} from '../helper/index'
export default class MyApp extends App {
static async getInitialProps() {
const events = await getEvents();
return {
events : events.events
};
}
render() {
const { Component, pageProps } = this.props;
return (
<div>
<ContextProvider events={this.props.events} >
<Component {...pageProps} />
</ContextProvider>
</div>
);
}
}
pages/[id].js
import { useRouter } from "next/router";
import Context from "../../config/Context";
/* Components */
import WordCounter from "../../components/word-counter/WordCounter";
function Post(props) {
const router = useRouter();
const context = React.useContext(Context);
return (
<React.Fragment>
<WordCounter />
</React.Fragment>
);
}
Post.getInitialProps = async ({ query}) => {
const detail = await getDetail(query.id) --> here I send the param and it seems never arrive to helper.js, why?
return {detail}
}
export default Post
Where is the problem? HELP!
THAANKS!

i think getInitialProps run in server and your helper function doesn't load there.
use fetch inside getInitialProps .

Related

Access data from GraphQL in class component

I have a code which access data from GraphQL API in an arrow function:
const LinkList = () => {
const { loading, error, data } = useQuery(CURRENCIES);
if (loading) return <Loader/>;
if (error) return <pre>{error.message}</pre>
return (
<div className="options">
{data.currencies.map((currency) => {
return (
<button
key={currency}
id={currency}
className="option"
>
{currency.symbol}
{currency.label}
</button>
);
})}
</div>
);
};
But I really need to implement this piece of code with access to it in a class component. I was searching a documentation with accessing data in a classes, but nothing.
Any ideas?
You can use #apollo/client package and we can use client.query directly in the class component
import {
ApolloClient,
gql,
InMemoryCache,
NormalizedCacheObject
} from '#apollo/client';
const client = new ApolloClient<NormalizedCacheObject> ({
cache: new InMemoryCache({}),
uri: 'https://countries.trevorblades.com'
});
import * as React from 'react';
const GET_Countries = gql`
query {
countries{
code
name
}
}
`;
class App extends React.Component {
getData = async () => {
let res = await client.query({
query: GET_Countries
})
console.log(res)
// Set the state to make changes in UI
}
componentDidMount() {
this.getData()
}
render() {
return "Test";
}
}
export default App;

NextJs: get server side props internal server problem with axios

Hello im going to get data from API using this https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props
but I'm using Axios instead of default like doc, same as the doc passing data through the props, already implement this but instead return data its return 500 internal server which is it works when on the localhost.
this is my home.js
import axios from "axios";
import Featured from "../components/Featured";
import ProductList from "../components/ProductList";
import styles from "../styles/Home.module.css";
export default function Home({ productList }) {
return (
<div className={styles.container}>
<Featured />
<ProductList productList={productList} />
</div>
);
}
export const getServerSideProps = async () => {
const res = await axios.get(
"http://localhost:3000/api/products" ||
"https://marrs-id.vercel.app/api/products"
);
const data = await res.data;
return {
props: {
productList: data,
},
};
};
am I missing something here?
You might want to store your API path in a .env file at the root of your project. So it can be used everywhere in your app and easy to maintain ?
Also I guess you can use Fetch instead of Axios for this case, something like this :
export const getServerSideProps = async () => {
const productListRes = await fetch(
`${process.env.API_ROOT}/api/products`
);
const productList = await productListRes.json();
return {
props: {
productList,
},
};
};

Nextjs not server side rendered when i wrapped component by auth

I using Next.js for SSR, after I try to make authentication for user client by Auth component following to my idea. But I have a problem when View Source page, it not loaded as HTML tag which empty root like create-react-app, now it my code in _app.js:
function MyApp({ Component, pageProps: { ...pageProps } }) {
const { auth } = Component;
return (
<>
{
auth ?
<Auth>
<Component {...pageProps} />
</Auth>
:
<Component {...pageProps} />
}
</>
)
}
Which Auth component is:
export const Auth = async (props) => {
const { children } = props;
const auth = await POST('http://localhost:7000/services/api/auth');
if (!auth) {
return <div>Loading...</div>
}
return children
}
And the page wrapped by auth component is:
export const getServerSideProps = async ctx =>{
const { id } = ctx.query;
try {
const postById = await GET(`http://localhost:7000/services/api/post/${id}`);
return {
props: {
post: postById
},
}
}
catch (err) {
console.log(err)
}
}
export default const DetailPost = (props) => {
return (
...
)
}
What should I do it for rendered with HTML DOM like server-side-rendering?

Could not find "store" in the context of "Connect(withRedux(MyApp))"

I am trying to do authentication in Nextjs using firebase and redux but I run into this error when I use connect from react-redux.
Note: I'm not a pro so do forgive me if my code seems bad.
import "../styles/global.scss";
import "bootstrap/dist/css/bootstrap.min.css";
import App from "next/app";
import { Provider, connect } from "react-redux";
import withRedux from "next-redux-wrapper";
import { auth, createUserProfileDocument } from "../firebase/firebase.utils";
import store from "../redux/store";
import { setCurrentUser } from "../redux/user/user.actions";
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: {};
//Anything returned here can be access by the client
return { pageProps: pageProps };
}
unsubscribeFromAuth = null;
componentDidMount() {
const { setCurrentUser } = this.props;
this.unsubscribeFromAuth = auth.onAuthStateChanged(async (userAuth) => {
if (userAuth) {
const userRef = await createUserProfileDocument(userAuth);
userRef.onSnapshot((snapshot) => {
setCurrentUser({
id: snapshot.id,
...snapshot.data(),
});
});
} else {
setCurrentUser(userAuth);
}
});
}
componentWillUnmount() {
this.unsubscribeFromAuth();
}
render() {
//Information that was returned from 'getInitialProps' are stored in the props i.e. pageProps
const { Component, pageProps, store } = this.props;
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
);
}
}
//makeStore function that returns a new store for every request
const makeStore = () => store;
const mapDispatchToProps = (dispatch) => ({
setCurrentUser: (user) => dispatch(setCurrentUser(user)),
});
const wrappedApp = withRedux(makeStore)(MyApp);
export default connect(null, mapDispatchToProps)(wrappedApp);
I have a sandbox link here.
Please help

NextJS: How to add screen loading for production build?

I want add screen loading in next js project. And I tried to do that with the Router component in next/router.
This is my _app.js in next.js project:
import {CookiesProvider} from 'react-cookie';
import App from 'next/app'
import React from 'react'
import {Provider} from 'react-redux'
import withRedux from 'next-redux-wrapper'
import withReduxSaga from 'next-redux-saga'
import createStore from '../src/redux/store'
import Router from "next/router";
import {Loaded, Loading} from "../src/util/Utils";
class MyApp extends App {
static async getInitialProps({Component, ctx}) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps({ctx})
}
return {pageProps}
}
render() {
Router.onRouteChangeStart = () => {
Loading()
};
Router.onRouteChangeComplete = () => {
Loaded()
};
Router.onRouteChangeError = () => {
Loaded()
};
const {Component, pageProps, store} = this.props;
return (
<CookiesProvider>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</CookiesProvider>
)
}
}
export default withRedux(createStore)(withReduxSaga(MyApp))
This is Loaded() and Loading() functions:
export const Loaded = () => {
setTimeout(() => {
let loading = 'has-loading';
document.body.classList.remove(loading);
}, 100);
};
export const Loading = () => {
let loading = 'has-loading';
document.body.classList.add(loading);
};
The code works well when the project is under development mode. But when the project is built, the loading won't disappear.
Do you know solution of this issue or are you suggesting another solution?
Using apollo client and react hooks you could do as follow.
Example:
import { useQuery } from '#apollo/react-hooks';
import gql from 'graphql-tag';
import { withApollo } from '../lib/apollo';
import UserCard from '../components/UserCard';
export const USER_INFO_QUERY = gql`
query getUser ($login: String!) {
user(login: $login) {
name
bio
avatarUrl
url
}
}
`;
const Index = () => {
const { query } = useRouter();
const { login = 'default' } = query;
const { loading, error, data } = useQuery(USER_INFO_QUERY, {
variables: { login },
});
if (loading) return 'Loading...'; // Loading component
if (error) return `Error! ${error.message}`; // Error component
const { user } = data;
return (
<UserCard
float
href={user.url}
headerImg="example.jpg"
avatarImg={user.avatarUrl}
name={user.name}
bio={user.bio}
/>
);
};
export default withApollo({ ssr: true })(Index);
More info here: https://github.com/zeit/next.js/tree/canary/examples/with-apollo
I added the following codes to a wrapper component and the problem was resolved.
componentDidMount() {
Loaded();
}
componentWillUnmount() {
Loading();
}

Resources