Closed mrtinkz closed 6 years ago
@mrtinkz, while experimenting with react-universally
and reactivesearch
I've added the following snippet into my SSR middleware and had no more issues so far. YMMV though...
if(typeof window === 'undefined') {
global.window = {
location: {
search: request.query
}
};
}
Thanks! We will implement a solid fix for this in the coming release, which will allow you to inject request.query
via props to the ReactiveBase
component, thereby conditionally picking query-params from the props if window
is not present in the scope.
@aol-nnov @mrtinkz
Besides window
issue, are you guys seeing any issue with the default styling? We use emotion for component scoped styling. Is it working for you guys properly? It'd be great if you can share a code snippet with us.
@metagrover, my experiments were very limited, unfortunately.
What I've done so far is a simple quckstart app similar to your examples, but with ssr. And the window issue was the only stopper for me.
I'll create a separate issue if I find anything down the road. I'm very limited with spare time now, sorry..
@metagrover indeed, there are issues with emotion on server side:
ReferenceError: document is not defined
at makeStyleTag (/Users/aol/react/react-universally/node_modules/emotion/src/sheet.js:39:22)
at StyleSheet.inject (/Users/aol/react/react-universally/node_modules/emotion/src/sheet.js:59:22)
at Object.<anonymous> (/Users/aol/react/react-universally/node_modules/emotion/src/index.js:15:7)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
I think we can follow the steps in https://emotion.sh/docs/ssr to resolve this
Have you added any external styles (from emotion) in your app? How come you didn't see these errors before when you ran the app using:
if(typeof window === 'undefined') {
global.window = {
location: {
search: request.query
}
};
}
The issue I'm seeing with emotion is that the styles don't get applied to Reactivesearch components on the initial render via SSR without any errors.
@metagrover no extra styles, only from reactivesearch
How come you didn't see these errors before
simple! I didn't read logs )))
As I told you, I barely have 30 minutes a day for this experiments now..
Thanks! I will look into it.
@metagrover @divyanshu013 I did not use emotion
, so the window
was the only problem I had. Sorry for the late reply.
@metagrover seems I'm stuck with ssr.. Could you please give me some glue?
just curl
-ed my page that was supposed to perform ssr and got
<div class="leftSidebar " data-reactid="32">
<!-- react-empty: 33 -->
<!-- react-empty: 34 -->
<!-- react-empty: 35 -->
<!-- react-empty: 36 -->
<!-- react-empty: 37 -->
</div>
instead of my SingleList
-s, MultiList
-s and DynamicRangeSlider
, which makes me think, that no data is present in props
.
Despite that I can see requests to ES server in logs (I've enabled them with the following command)
curl -XPUT 'http://<ip>:9200/<my_index>/_settings?preserve_existing=true' -d '{
"index.indexing.slowlog.threshold.index.debug" : "0s",
"index.search.slowlog.threshold.fetch.debug" : "0s",
"index.search.slowlog.threshold.query.debug" : "0s"
}' -H "content-type: application/json"
As I already told you, I'm using react universally (redux-opinionated branch) as my ssr boilerplate.
Also, if I navigate to that page via js-enabled browser, contents is rendered just fine (but it's client-side rendering)
Any hints would be highly appreciated!
@aol-nnov Thanks for the detailed info. I will need some time to figure out the solution for this.
(Heads up: I have very little experience with SSR so this could be totally wrong):
A possible way to get this to work:
Try passing the data from the ES query as props to the SingleList component and see if it gets rendered then? SingleList returns null
when there is no data which is apparently happening here. Refer this prop here to pass the data to the SingleList component.
I'm not too sure if that will work though, since we check for options
prop changes in componentWillReceiveProps. So in order to try this out properly, I suggest you set the options
prop with a delay, so that the updates are handled by the component.
If it works in any of the above case, we will wire up the things in the library to support this properly. If you have any better solution in mind that can work, we are open to your suggestions.
@metagrover thank you for responce!
Today I've stumbled upon profound SO answer on react lifecycle callbacks, and at first sight, it could be fixed by changing componentWillReceiveProps
to componentWillUpdate
since
componentWillReceiveProps(nextProps,nextState)
This function is called every time props are received except the first render
And that first render happens on server.
Also, as per that answer:
Does the change in state/props requires to data to be updated?
Example, parent container which formats data received after api call and passes the formatted data to children.
componentWillUpdate
I'll try that later and report back.
Hey @aol-nnov, we use componentWillReceiveProps
to selectively handle several types of prop updates accordingly. We can support the initial data rendering via constructor
here and not componentWillUpdate
, since it gets called on every state and prop changes which is not what we want here.
So, if you're at it, try it with constructor
or componentDidMount
method.
@metagrover will do!
Thank you for the hints!
@metagrover it seems, that componentDidMount
is not fired on server side, so, I've added following snippet to the bottom of constructor:
this.updateQueryOptions(this.props);
this.updateQuery(Object.keys(this.state.currentValue), this.props);
also I've added some logging to mapStatetoProps and figured out that on server side it is fired only twice and state seems to be empty:
{ components: [],
watchMan: {},
queryList: {},
queryOptions: {},
dependencyTree: {},
appbaseRef:
AppbaseClient {
url: '192.168.248.4:9200',
protocol: 'http',
credentials: null,
appname: 'myapp',
headers: {} },
config:
{ url: 'http://192.168.248.4:9200',
app: 'myapp',
credentials: null,
type: '*' },
hits: {},
aggregations: {},
queryLog: {},
selectedValues: {},
isLoading: {},
stream: {},
streamHits: {},
timestamp: {},
headers: {} }
on the client side there are a hell more calls to it... so, no luck as of now...
This blows my mind, but it looks like a key to success. ))
What do you think, @metagrover ?
I was aware of the fact that the store isn't getting updated 😓. The medium post looks interesting though. Need to check up on redux store management with SSR. Will get to this shortly. Thanks!
Hello! Any news on SSR?
I'd be really glad to know if there is any progress...
Hello everyone,
Primary support for SSR has been added. We should be able to wrap it up in this week. You can check the progress on the ssr branch.
Cheers!
@metagrover you are my hero! :-D
Mine too ❤️
Fantastic , thank you....
SSR support is out in v2.5.0
🎉
Issue Type:
Reactive Base component have server side rendering issues, it tries to uses the window which will not be available on the server. Description:
I have been giving it a try and found that the Reactive Base component does have a server side rendering issues, it tries to uses the window which will not be available on the server. Not sure if other components have similar issues, but it would be great if all of the components have SSR support. I got it working by rendering it only on the client side but that's a bad practice and is not recommended.
Screenshots:
Minimal reproduction of the problem with instructions:
Reactivesearch version: 2.2.0
Browser: [all | Chrome XX | Firefox XX | Edge XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
Anything else: