Open ianobermiller opened 8 years ago
+1 please.
+1
There are some tips making wrapper #429 or other ways. But I think they're run out. I could solve the warnings without wrappers. I have updated 0.16.2 successful by fixing like this.
Serverside
content = ReactDOM.renderToString(
<RoutingContext
{...renderProps}
radiumConfig={{userAgent: req.headers['user-agent']}} />
);
ClientSide
<StyleRoot />
the top of entry.let App = React.createClass({ ... })
App = Radium(App);
let RootApp = React.createClass({
displayName: 'RootApp',
render() {
return (
<StyleRoot>
<App {...this.props} />
</StyleRoot>
);
}
});
export default RootApp;
This will solve the warnings and print clean console.
I think that it would be interesting to document where < StyleRoot />
should be used in the rendering tree when we are using radium
with react-router
or redux
.
@bsdo64 Are you sure that that works? It won't even let me render without the StyleRoot
. @ianobermiller Is StyleRoot
supposed to be used on both server an client? I'm wrapping by top level component in StyleRoot
and am passing radiumConfig
to the RouterContext
, but cannot get rid of the checksum issue.
And just so as I posted this, I got it working. The solution was to just always wrap the top level component within StyleRoot
. @oliviertassinari Using redux
and react-router
: wrap your RouterContext
within redux' Provider
component. And use StyleRoot
in your top-level route handler.
@johanneslumpe For some reason, wrapping my my route handler like so:
// shared/routes.js
<StyleRoot>
<Route path="/" component={App} >
<IndexRoute component={PostContainer} />
<Route path="/post/:slug" component={PostDetailView} />
</Route>
</StyleRoot>
returns an error beginning with: Cannot read property 'need' of undefined
.
For context, the part of my server.js
that handles the actual server-side rendering is:
// server/server.js
fetchComponentData(store.dispatch, renderProps.components, renderProps.params)
.then(() => {
const initialView = renderToString(
<Provider store={store}>
<RouterContext {...renderProps} radiumConfig={{ userAgent: req.headers['user-agent'] }} />
</Provider>
);
const finalState = store.getState();
res.status(200).end(renderFullPage(initialView, finalState));
})
.catch(() => {
res.end(renderFullPage('Error', {}));
});
});
@gigavinyl try this:
/// App.js
function App({ children }) {
return (
<StyleRoot>
{children}
</StyleRoot>
);
}
export default radium(App);
// shared/routes.js
<Route path="/" component={App} >
<IndexRoute component={PostContainer} />
<Route path="/post/:slug" component={PostDetailView} />
</Route>
Furthermore, for whatever reason it didn't work for me to pass in the radiumConfig
via RouterContext
. I am using the following createElement
function to pass it in:
const createElement = (Component, props) => (
<Component
{...props}
radiumConfig={{ userAgent: req.headers['user-agent'] }}
/>
);
So rendering the RouterContext
looks like this:
renderToString(
<RouterContext
{...renderProps}
createElement={createElement}
/>,
);
This works like charm for me.
// edit
added decorator to App
@johanneslumpe Hmm, didn't work for me...
For context, I'm using redux and the part of my server.js
file that handles server-side rendering is:
fetchComponentData(store.dispatch, renderProps.components, renderProps.params)
.then(() => {
const createElement = (Component, props) => (
<Component
{...props}
radiumConfig={{ userAgent: req.headers['user-agent'] }}
/>
);
const initialView = renderToString(
<Provider store={store}>
<RouterContext {...renderProps} createElement={createElement} />
</Provider>
);
const finalState = store.getState();
res.status(200).end(renderFullPage(initialView, finalState));
})
.catch(() => {
res.end(renderFullPage('Error', {}));
});
and my App.js
container is:
import React, { Component, PropTypes } from 'react';
import PostListView from '../container/PostListView/PostListView';
import PostCreateView from '../components/PostCreateView/PostCreateView';
import { connect } from 'react-redux';
import { StyleRoot } from 'radium';
import * as Actions from '../redux/actions/actions';
class App extends Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
children: PropTypes.object.isRequired,
}
render() {
const { dispatch } = this.props;
return (
<StyleRoot>
<div className="container">
{ this.props.children }
</div>
</StyleRoot>
);
}
}
export default connect()(App);
I applogize for my n00bie-ness :grin:.
@gigavinyl Can you be more descriptive than "It didn't work"? ;)
@johanneslumpe Upon initially loading the page, I'm met with this error:
Radium: userAgent should be supplied for server-side rendering. See https://github.com/FormidableLabs/radium/tree/master/docs/api#radium for more information.
Either the global navigator was undefined or an invalid userAgent was provided. Using a valid userAgent? Please let us know and create an issue at https://github.com/rofrischmann/inline-style-prefixer/issues
@gigavinyl Can you please try to use the @Radium
decorator on your App
component? I think it's missing in my example above.
@johanneslumpe Thanks! It works perfectly now with no errors :smile:.
:+1:
@johanneslumpe / @ianobermiller - are there docs on what Radium will or will not do in SSR? Would be very helpful to at least have an FAQ.
For example: if React SSR is used to generate an .html page that then does not hydrate with client-side JS, will :hover
effects still work? (do you support generating that stylesheet initially?)
Just so people aren't confused.