Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation: Confusion over Apollo/Redux implementation #282

Closed
dottjt opened this issue Nov 1, 2018 · 14 comments
Closed

Documentation: Confusion over Apollo/Redux implementation #282

dottjt opened this issue Nov 1, 2018 · 14 comments

Comments

@dottjt
Copy link

dottjt commented Nov 1, 2018

In the redux section it mentions this code:

// Grab the state from a global variable injected into the server-generated HTML
const preloadedState = window.__PRELOADED_STATE__;

// Allow the passed state to be garbage-collected
delete window.__PRELOADED_STATE__;

// Create Redux store with initial state
const store = createStore(counterApp, preloadedState || initialState);

// Tell react-snap how to save Redux state
window.snapSaveState = () => ({
  __PRELOADED_STATE__: store.getState()
});

However, I suppose the confusion is for me - where does this code actually go?

@stereobooster
Copy link
Owner

in the same file where you initialise Redux, in the same file where you boot React, in most cases this is index.js - top most file.

@dottjt
Copy link
Author

dottjt commented Nov 1, 2018

Excellent, thank you for the prompt response. So I'm imagining then that react-snap basically goes through all your source files and looks for window.snapSaveState to figure out the state of things.

@stereobooster
Copy link
Owner

stereobooster commented Nov 1, 2018

It starts real server, serves your app from it, it uses real browser to crawl it. It doesn't know anything about file structure or technology. You can use anything and organise it whatever you want

@dottjt
Copy link
Author

dottjt commented Nov 1, 2018

Sorry to be a huge noob, but I've been trying to get this to work with Apollo, and I imagine a lot of other people have been struggling as well. I've been using this guide as a vague reference, also using the redux example. https://www.apollographql.com/docs/react/features/server-side-rendering.html

I've managed to come up with something like this so far, but I'm not 100% sure if it's correct. Thought I might put it out there for other people as well :)

const preloadedState = (<any>window).__APOLLO_STATE__;

delete (<any>window).__APOLLO_STATE__;

const cache = new InMemoryCache().restore((<any>window).__APOLLO_STATE__);

const stateLink = withClientState({
  cache,
  defaults,
  resolvers: { Mutation: { ...mutations, } },
  typeDefs: [ index, sentenceTypes, optionTypes ],
});

const client = new ApolloClient({
  cache,
  link: ApolloLink.from([stateLink, new HttpLink({uri: 'https://nx9zvp49q7.lp.gql.zone/graphql'})]),
});

(<any>window).snapSaveState = () => ({
  __APOLLO_STATE__: client.extract(),
});

Although I don't believe it works, getting this error when building:
throw new Error('Cannot write to stream after nil');

Will have to do some extensive playing around, I think. At the very least it works when running the app, it may be related to something else.

@stereobooster
Copy link
Owner

stereobooster commented Nov 1, 2018

Sorry to be a huge noob

If my words made you feel like that, I'm sorry I didn't mean it. You are doing fine. There are no stupid questions, there are people who can't answer some questions...

Although I don't believe it works, getting this error when building:

This is different error. It is reported somewhere else, I believe there is even fix somewhere in PRs

Just inspect result HTML files, if they contain <script> __APOLLO_STATE__ = {.... If they than saving of state works

@dottjt
Copy link
Author

dottjt commented Nov 1, 2018

Just inspect result HTML files, if they contain <script> APOLLO_STATE = {.... If they than saving of state works

Oh wow, that is a really helpful piece of information. Thank you.

Just a question: Is it the case that I need to run (<any>window).snapSaveState basically anytime the apollo/redux state changes in a different component/page? That's the impression I'm getting. Or at least before component render?

@stereobooster
Copy link
Owner

window.snapSaveState is used by react-snap itself, it will call function right before it will consider page rendered.

@dottjt
Copy link
Author

dottjt commented Nov 1, 2018

Thanks @stereobooster. I've got it all working, however I've come to the realisation that react-snap won't work for my project. Basically, I've noticed it will render the state of the application at a particular moment, but all the actual javascript functionality has been removed - so none of the buttons work to dynamically generate things.

Ah well, trial and error - I may have a look at something like Razzle. But still, really good to know and a great library you've created - will definitely use it if I'm building something more static :)

@stereobooster
Copy link
Owner

, but all the actual javascript functionality has been removed - so none of the buttons work to dynamically generate things.

You just catched another bug. If you use CRA2, there is a bug #264. react-snap should leave all JS in place.

@dottjt
Copy link
Author

dottjt commented Nov 1, 2018

Oh, thank god - nice to know I'll give it another try.

@dottjt
Copy link
Author

dottjt commented Nov 1, 2018

I implemented the fix. Holy Crap, I can't believe my application is available as a static site and I don't have to go through the pain of setting up SSR. You are a genius, this library is incredible. Thank you @stereobooster

@stereobooster
Copy link
Owner

Just to make sure, you understand that if you use dynamic API when you do snapshots your static content can deviate from what your API returns, right?

@dottjt
Copy link
Author

dottjt commented Nov 2, 2018

Yes, I understand that aspect. Which is fine because the dynamic aspect of the page isn't really specific to SEO, so it doesn't really matter what it shows in the snapshot.

But I kind of see it as a positive thing anyway, because the way the app is written it will display different information in each snap per build, which I imagine is good for SEO as it demonstrates that the content is remaining up to date.

@vishnup95
Copy link

@dottjt can you please share the code with which you got it working for Appollo?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants