/src/routes/home index.js: fetch
import React from 'react';
import Home from './Home';
import fetch from '../../core/fetch';
import Layout from '../../components/Layout';
export default {
path: '/',
async action() {
const resp = await fetch('/graphql', {
method: 'post',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: '{news{title,link,contentSnippet}}',
}),
credentials: 'include',
});
const { data } = await resp.json();
if (!data || !data.news) throw new Error('Failed to load the news feed.');
return {
title: 'React Starter Kit',
component: <Layout><Home news={data.news} /></Layout>,
};
},
};
*server.js *
app.use('/graphql', expressGraphQL(req => ({
schema,
graphiql: process.env.NODE_ENV !== 'production',
rootValue: { request: req },
pretty: process.env.NODE_ENV !== 'production',
})));
debug log,expressGraphQL will run twice
add console.log('fetch finished') after await fetch('/graphql'.....) in /src/routes/home index.js file, then refresh the browser, the console in browser and the console of my laptop both printed fetch finished. Is this expected? I have thought api requests only happened on the server.
Same here, all fetches are ran twice. It seems there is no way in which the state is saved in the HTML so it doesn't need to be refetched on the client.
I am now passing the data found server-side in action() to the html and feeding it in client.js to the action() clientside.
@jorrit Passing data down inside an element and picking it up client side when the rerender check happens is the correct thing to do. Example in this project is incomplete.
This is not a bug my friend.
since the routes are universal, it will first run on the server and then run again on the client.
This is basically one of the major point of using isomorphic architecture: to prefetch the data on the server.
I personally use redux for data handling. So basically when request comes in, on server side I would fetch the data, put the data in redux store, render the route, and at last, pass down the rendered page with the redux state to the client.
Then on the client side, I would check if the data is already in the redux store. if it is, then there is no need to fetch the data again.
export default {
path: '/data',
async action({ store }) {
const data = store.getState().data;
if (!data) {
console.log('no data. fetch now');
await store.dispatch(fetchData());
}else{
console.log('already got the data. don\'t fetch');
}
return {
component: <Layout><DataView data={data}/></Layout>,
// I'm passing the data to the component just for demonstration purposes
// would normally use higher order component to decorate the <DataView> with the data when using redux
};
},
};
You're right, it is not a bug. It is a consequence of the fact that the default react-starter-kit branch does not contain a store and doesn't serialize the data in HTML. As such, the server side prefetching does not prevent client-side fetching. Maybe something simple can be added without pulling in redux.
@DylanYasen, two questions....
1) is your code sample pseudo code, in that would that if (!data) check more then just existence, or would it be diving into the type of data to validate its contents?
2) What about in the case of a dynamic route. Say a VideoDetails page where the url is of type domain.com/video/24234 if all we do is check for existence... as you browse from videodetails page for video1 to videodetails page for video2 the content would never change since that check if (!data) will always be true.
Did you find any recommended solution for this?
For your specific case store.getState() can be replaced by a  selector like
const data = getVideo(store.getState(), vedioId);
implement the getter according to any business logic.
On Thu, May 4, 2017 6:42 AM, Dan Van Brunt [email protected] wrote:
This message is eligible for Automatic Cleanup! ([email protected]) Add
cleanup rule | More info
@DylanYasen, two questions....
is your code sample pseudo code, in that would that if (!data) check more
then just existence, or would it be diving into the type of data to validate
its contents?
What about in the case of a dynamic route. Say a VideoDetails page where
the url is of type domain.com/video/24234 if all we do is check for
existence... as you browse from videodetails page for video1 to videodetails
page for video2 the content would never change since that check if (!data)
will always be true.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
Thanks & Regards Shishir Arora
Most helpful comment
This is not a bug my friend.
since the routes are universal, it will first run on the server and then run again on the client.
This is basically one of the major point of using isomorphic architecture: to prefetch the data on the server.
I personally use redux for data handling. So basically when request comes in, on server side I would fetch the data, put the data in redux store, render the route, and at last, pass down the rendered page with the redux state to the client.
Then on the client side, I would check if the data is already in the redux store. if it is, then there is no need to fetch the data again.