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,
},
};
};
Related
I am trying to add dynamic data from one file to another and am having issues with that.
The data I am trying to load from
path: /src/components/Subnav.js
import React, { Component } from "react";
class Subnav extends Component {
static async getInitialProps(ctx) {
const res = await fetch("https://api.github.com/repos/vercel/next.js");
const json = await res.json();
return { stars: json.stargazers_count };
}
render() {
return <div>Next stars: {this.props.stars}</div>;
}
}
export default Subnav;
The code where I want the above data in
import React from "react";
import Subnav from "../src/components/Subnav";
function Page({ json }) {
return (
<subNav />
)
}
output in the browser
<div>Next stars: </div>
The expected output in the browser
<div>Next stars: 88542</div>
Issue:
As you can see above, I am just seeing the static text which is "Next stars" however, i am not seeing the data from the JSON
getInitialProps is data fetching method for page, it means you only can use it inside /pages folder. If you want fetching data for components, you can use useEffect.
import React, { useEffect, useState } from "react";
const Subnav = () => {
const [stars, setStars] = useState(null);
useEffect(() => {
const getStars = async () => {
const res = await fetch("https://api.github.com/repos/vercel/next.js");
const json = await res.json();
setStars(json.stargazers_count)
}
getStars();
}, [])
return <div>Next stars: {stars}</div>
}
export default Subnav;
I am trying to embed a Forge Viewer in a React Component. There is an example on the GitHub but it is not quite working for me. It seems there are some missing elements.
Is there a way we can get a step by step implementation of the viewer in React?
This is my only missing object at the moment. I have already fetched the model from a bucket, converted it into svf and fetched a urn to be passed to the viewer.
Any help out there, possibly without using redux?
You can create a component and a helper:
Helper: viewer-helper.js
import axios from 'axios'
/* global Autodesk, THREE */
const url_base = 'http://localhost:4000/'
// Get token from server
const getToken = async () => {
const {data} = await axios.get(url_base + 'forge/auth');
return data
}
export const initializeViewer = async (urn) => {
const token = await getToken()
const viewerOptions = {
env: 'AutodeskProduction',
accessToken: token,
api: 'derivativeV2',
};
var viewerContainer = document.getElementById('viewerContainer')
var viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerContainer, {})
Autodesk.Viewing.Initializer(viewerOptions, () => {
viewer.start();
Autodesk.Viewing.Document.load(`urn:${urn}`, (doc) =>{
var defaultModel = doc.getRoot().getDefaultGeometry();
viewer.loadDocumentNode(doc, defaultModel);
})
})
}
Component:
import React,{useEffect} from 'react'
import {initializeViewer} from './viewer-helper'
const Viewer = () => {
const urn ='dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6bWFsbGF2ZW50dXJhc2FuanVhbmRlbHVyaWdhbmNob19idWNrZXQvMTU3OTUyNjAwMzkwM19NYWxsJTIwQXZlbnR1cmElMjBTSkxfRXN0cnVjdHVyYXMucnZ0'
useEffect(() => {
initializeViewer(urn)
}, [])
return (
<div>
<div id='viewerContainer'></div>
</div>
)
}
export default Viewer
App.js
import React from 'react';
import './App.css';
import Viewer from './components/viewer/Viewer'
function App() {
return (
<div className="App">
<Viewer/>
</div>
);
}
export default App;
Please try React Forge Viewer Component:
https://www.npmjs.com/package/react-forge-viewer
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 .
I've used getInitialProps to load a large json file onto an individual page. Since it's a rather large json, I was wondering how I should go about loading it onto the index page to start with. The subpages should load it only if someone goes onto a subpage directly bypassing the index and it's not in the props already. The docs are a bit confusing on loading onto the _app compared to individual components. Also, not clear how to do a check within then getInitialProps if the props are already fetched...
import App from 'next/app'
import React from 'react'
import withReduxStore from '../store/with-redux-store'
import { Provider } from 'react-redux'
import "isomorphic-fetch"
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let res = await fetch('https://xxxx.json', { mode: 'no-cors' });
let productParams = await res.text().then((data) => {
return (data ? JSON.parse(data) : {})
})
.catch((error) => {
console.error("Something bad happened", error);
});
console.log(`Show data fetched. Count: ${Object.keys(productParams).length}`);
return { productParams, topState: "loaded" }
}
render() {
return (
<Provider store={reduxStore}>
<Component {...this.props} />
</Provider>
)
}
}
export default withReduxStore(MyApp)
________________________________________________
class SubPage extends React.Component {
static async getInitialProps({ reduxStore, topState }) {
reduxStore.dispatch(loadInitialState());
if (topState != "loaded") {
let res = await fetch('https://xxxxxx.json', { mode: 'no-cors' })
let productParams = await res.json();
return { productParams }
} else {
return {}
}
}
state = { ...this.props, riskType: "xxx" }
componentDidMount() {
console.log(this.state);
}
render() {
return (
<Layout>
<SubComponent />
</Layout>
)
}
}
const mapStateToProps = (state) => {
return state;
};
const mapDispatchToProps = (dispatch) => {
return {
loadInitialState: () => {
dispatch({ type: "LOAD_INITIAL_STATE" });
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(SubPage)
If I go to the main page, the _app loads the json, then if I click on the subpage link, its no longer in the props. Only when I reload the subpage, it appears in the props again. What am I doing wrong?
From what I can gather, your example seems to have several issues. But the main ones that would need addressing for your scenario to work are:
Component on _app.js is actually a prop passed to your MyApp component.
Since you are overriding it, you should call App.getInitialProps inside your static MyApp.getInitialProps. That would actually trigger calls to your page's own getInitialProps.
The props returned from getInitialProps in _app.js are sent as pageProps to MyApp.
Putting it all together would look something like this:
import App from 'next/app'
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
MyApp.getInitialProps = async (appContext) => {
// calls page's `getInitialProps` and fills `appProps.pageProps`
const appProps = await App.getInitialProps(appContext);
// Fetch your json file
const res = await fetch('https://xxxx.json', { mode: 'no-cors' });
const productParams = await res.json();
return { ...appProps, productParams, topState: "loaded" };
}
export default MyApp
Just bear in mind that setting a getInitialProps from your custom App will force every page on your app to be server side rendered and void static optimization, entirely. You can read more about custom App on its official documentation section.
I am trying to call a api continuously at 3 seconds interval.I am trying with async and setInterval but not working at all.
Let's look at my code below
component.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { connect } from 'react-redux';
import { fetchMarketCap } from '../Actions/Marketcap';
class Header extends Component{
componentDidMount(){
setInterval(this.props.fetchMarketCap(), 3000);
}
render(){
const marketcap = this.props.marketcap.map(coin => (
<div key={coin.CoinInfo.Id}>
<h5>{coin.CoinInfo.Name}</h5>
<h5>{coin.RAW.USD.CHANGE24HOUR}</h5>
</div>
));
return (
<div>
{marketcap}
</div>
);
}
}
const mapStateToProps = state => ({
marketcap: state.marketcap.coins
});
export default connect ( mapStateToProps, { fetchMarketCap } )(Header);
and expected action file Marketcap.js
import { FETCH_MARKET_CAP, FETCH_MARKET_CAP_SUCCEED, FETCH_MARKET_CAP_FAILED } from './Types';
export const fetchMarketCap = async () => async dispatch => {
const res = await fetch('https://min-api.cryptocompare.com/data/top/mktcapfull?limit=10&tsym=USD&api_key=46e898b0b5d0319ab6fb94aae5ed2f1a388ff650bffefa1f32f5af1479766b4f');
const response = await res.json()
.then( marketcaps =>
dispatch({
type: FETCH_MARKET_CAP_SUCCEED,
payload: marketcaps.Data
})
)
}
but in console SyntaxError: Unexpected token (10:52) in Marketcap.js.Unexpected token (10:52)
You may need an appropriate loader to handle this file type. in the console.How can i solve it?
One obvious thing is the use of the async keyword... Get rid of the first async like so:
export const fetchMarketCap = () => async dispatch => {
const res = await fetch('https://min-api.cryptocompare.com/data/top/mktcapfull?limit=10&tsym=USD&api_key=46e898b0b5d0319ab6fb94aae5ed2f1a388ff650bffefa1f32f5af1479766b4f');
const response = await res.json()
.then( marketcaps =>
dispatch({
type: FETCH_MARKET_CAP_SUCCEED,
payload: marketcaps.Data
})
)
}
The way I've done this in the past in by using Redux-Sagas middleware. It lets you poll every x seconds, and allows you to start and stop the polling using actions.
See this answer for more details: https://stackoverflow.com/a/52422831/6640093