I am new to react/redux I little confused with server side rending in react/redux, Yes i saw some example on the internet but when i tried with mock api with external server , server side rendering is not working .
cat.js
import React from 'react';
import {render} from 'react-dom';
import {connect} from 'react-redux';
import * as mockApi from '../Actions/mockActions';
class Cat extends React.Component{
componentWillMount(){
this.props.getMockApi();
}
render(){
return(
<div>
Hello Dude
{this.props.mock.data.map((data,i) => {
return <li key={i}>{data.email}</li>
})}
</div>
)
}
}
const mapStateToProps = (state) => {
return {
mock:state.mock
}
};
const mapDispatchToProps = (dispatch) => {
return {
getMockApi:() => dispatch(mockApi.getMockData())
}
};
export default connect(mapStateToProps,mapDispatchToProps)(Cat);
mockActions.js
import axios from 'axios';
import * as types from './actionTypes';
export function getMockData() {
return dispatch => {
return axios.get('http://jsonplaceholder.typicode.com/users').then(response => {
dispatch(setThisData(response.data))
})
}
}
export function setThisData(data) {
return {
type:types.MOCK_API,
payload:data
}
}
App.js
import React from 'react';
import {render} from 'react-dom';
import Cat from './components/cat'
import {Provider} from 'react-redux';
import configureStore from './Store/configureStore';
import { createStore ,applyMiddleware,compose} from 'redux';
import counterApp from './Reducers'
import thunk from 'redux-thunk';
if(typeof window !== 'undefined'){
// 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__
const store = createStore(counterApp, preloadedState, compose(applyMiddleware(thunk)))
render(
<Provider store={store} >
<Cat/>
</Provider>
,
document.getElementById('app')
)
}
devServer.js
import express from 'express';
import path from 'path';
import webpack from 'webpack';
import webpackMiddleware from 'webpack-dev-middleware'
import webpackHotMidleware from 'webpack-hot-middleware';
import bodyParser from 'body-parser';
import React from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux';
import counterApp from '../../src/client/ReduxServer/Reducers';
import App from '../../src/client/ReduxServer/components/cat';
import { renderToString } from 'react-dom/server'
import webpackConfig from '../../webpack.config.dev';
let app = express();
app.use(bodyParser.json());
app.use(express.static('public'))
const compiler = webpack(webpackConfig);
app.use(webpackMiddleware(compiler, {
hot: true,
publicPath: webpackConfig.output.publicPath,
noInfo: true
}));
app.use(webpackHotMidleware(compiler));
// app.get('/*', (req, res) => {
// res.sendFile(path.join(__dirname, '../../index.html'))
// });
//Redux Start
app.use(handleRender);
function handleRender(req,res) {
const store = createStore(counterApp);
const html = renderToString(
<Provider store={store} >
<App/>
</Provider>
)
const preloadedState = store.getState();
// Send the rendered page back to the client
res.send(renderFullPage(html, preloadedState))
}
function renderFullPage(html, preloadedState) {
console.log(preloadedState)
return `
<!doctype html>
<html>
<head>
<title>Redux Universal Example</title>
</head>
<body>
<div id="app">${html}</div>
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
</script>
<script src="bundle.js"></script>
</body>
</html>
`
}
//Redux Ends
app.listen(3000, () => {
console.log('Listening')
});
Right now this will only server render the hello dude but not the mock Api call data .I know that missed to fetch the data from server side but the point is what will i do If ihave to render a two components and that component has 5 api reuqest ,And how to fecth the correct api Request
Right Now My client Side Prefecthed state will look like this
window.__PRELOADED_STATE__ = {"mock":{"data":[]}}
Yes! This is where server-side rendering for React comes in. In this article, I want to introduce you to server-side rending (SSR) with React, reasons to use it, and some popular frameworks for rendering React on the server side.
js is used for server side rendering of react application . React along with other framework like angular and vue. js are traditional client side framework ,they run in browser but there are technology to run this framework on server side, and next.
Server-side rendering (SSR) is an application's ability to convert HTML files on the server into a fully rendered HTML page for the client. The web browser submits a request for information from the server, which instantly responds by sending a fully rendered page to the client.
Ok, to make this clear, you've created the code to handle server rendering. However, it doesn't load the data that is supposed to be fetched right?
You've done the first step, great! The next step is to load the actual dynamic data to the store. Let's look at this code here
function handleRender(req,res) {
const store = createStore(counterApp);
const html = renderToString(
<Provider store={store} >
<App/>
</Provider>
)
const preloadedState = store.getState();
// Send the rendered page back to the client
res.send(renderFullPage(html, preloadedState))
}
What happened is that you created a store. The store is used to render the html into a string. Then you get the store state and put it into preloadedState.
This is great accept that renderToString will not call this.props.getMockApi(); as you would expect.
Instead, you have to fetch the state before you call renderToString();
In this case, what you could do is as following. (Note that this is just an example, you probably want to use something more general in production, especially if you use something like react-router.)
import * as mockApi from '../Actions/mockActions';
function handleRender(req, res) {
const store = createStore(counterApp);
store.dispatch(mockApi.getMockData())
// And since you used redux-thunk, it should return a promise
.then(() => {
const html = renderToString(
<Provider store={store}>
<App/>
</Provider>
)
const preloadedState = store.getState();
// Send the rendered page back to the client
res.send(renderFullPage(html, preloadedState))
});
}
Simple isn't it? ;D, nah just joking. This is one part of react where there's not really an exact solution to the problem yet.
Personally, if I had the choice to go back in time, I'd tell myself to learn other stuff other than server rendering. There are other techniques such as code splitting, lazy loading, etc that I could've used instead. With server rendering, if the javascript arrives long after the user has seen the initial page, they might get frustrated by other things that require js. For example in my case, some links are not working, some buttons don't do anything, etc.
I'm not saying that server rendering is not good. It's an interesting technique, just that there are other techniques that are more beneficial to learn first (Oh, and server rendering basically locks you to use nodejs for your backend). Good luck to you :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With