0

Can i do server side rendering for my page without using redux or any store container and just react router. My initial page fetches some data from the api. How should i pass this down to the the react component on the server. If i use the window variable on the server i get an error saying window is undefined. Any help would be good.

I do not want to use, redux. I tried getting the initial data state, how do i pass this to the components on the server side. Using window variable doesnt help as window is not defined on the server.

clientRouter.get('/', (req, res) => {
  match({routes : routes, location: req.url}, (err, redirect, props) => {
   if (err) {
      res.status(500).send(err.message)
    } else if (redirect) {
      res.redirect(redirect.pathname + redirect.search)
    } else if (props) {

        let todos = [{id: 1, title: "Hey loo"}, {id: 2, title: "Meoww"}];
        props.todos = todos
        **** how do i pass the todos state down to the components****
        const appHtml = renderToString(<RouterContext {...props}/>);
        res.send(renderPage(appHtml, todos))
      // if we got props then we matched a route and can render
    } else {
      // no errors, no redirect, we just didn't match anything
      res.status(404).send('Not Found')
    }
  })
})

The above did not work

function renderPage(appHtml, state) {
  let initialState = JSON.stringify(state);
  return `

    <html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Judo Heroes - A Universal JavaScript demo application with React</title>
    <link rel="stylesheet" href="./../build/${cssSrc}">
  </head>
  <body>
    <div id="main">${appHtml}</div>
    <script>window.INIT_STATE = ${initialState}</script>
    <script src=./../build/${jsSrc}></script>
  </body>
</html>
   `
}

1 Answer 1

3

I have created a boilerplate in which the SSR is enabled using EJS.

I have used EJS(Embedded JS) for injecting the markup in html with preloaded data.

You can hit the api in server.js and load the data as preloadedData in your html markup

     // universal routing and rendering
     app.get('*', (req, res) => {
       // if the current route matched we have renderProps
       match(
         { routes, location: req.url },
         (err, redirectLocation, renderProps) => {

              // in case of error display the error message
             if (err) {
               return res.status(500).send(err.message);
             }
             // in case of redirect propagate the redirect to the browser
             if (redirectLocation) {
               return res.redirect(302, redirectLocation.pathname + redirectLocation.search);
             }
             // generate the React markup for the current route
             let markup = "";
             if (renderProps) {
             let preloadedData = [];
               fetch("http://example.com").then(function (data) {
                 preloadedData = [data.data];
                 renderSSRPage(res, preloadedData, renderProps);
               }.bind(this)).catch(function (err) {
                 preloadedData = [{ error: true }];
                 renderSSRPage(res, preloadedData, renderProps);
                 console.warn('Error in server.js ', err)
               });
               res.render('index', {
                 markup,
                 preloadedData: JSON.stringify(preloadedData)
               });
             }
           }
         )
     }
Sign up to request clarification or add additional context in comments.

5 Comments

I decided to move to a store. Also why do you need a templating engine. You can use renderToString directly right??
renderToString is used only when you don't have any dynamic data in your page. And renderToString will render your markup to client side but you cannot load elements which is based on api data from your backend server
why not, make an api call , fetch data, then create an instance of your store and state object on the server, pass it down as the initial state to the client, all you need will be renderToString. I've done this on a working product in production.. :)
In your question you have mentioned that you don't want to use the store. The solution I suggested is for passing data without usage of store
You have working code using store. Answer it in a different question and this answer is for the question you asked

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.