Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React component rendered twice using server side rendering

I have an app where I configured server side rendering. Everything is working nice and my component is rendered on the server. The problem is that I get my component rendered twice on the screen. One comes from <div id="content"><%- content %></div>that I am using for server rendering and one comes from <script src="http://localhost:3001/bundle.js"></script>. I use webpack to make two bundles for my server and client. Why is this happening and how can I fix this?

views/index.ejs

<body>
  <div id="app"></div>
  <div id="content"><%- content %></div>
  <script src="http://localhost:3001/bundle.js"></script>
</body>

index.js

app.use(Express.static(path.join(__dirname, '../', 'dist')))

app.use(serverRenderer)
app.get('*', (req: Object, res: Object) => {
  res.render('index', {content: req.body})
})

serverRender

import React from 'react'
import ReactDOM from 'react-dom/server'
import { match, RouterContext } from 'react-router'
import routes from '../client/routes.js'

async function render (component) {
  const content = ReactDOM.renderToString(component)
  return content
}

async function getMatchParams (routes, currentUrl) {
  return new Promise((resolve, reject) => {
    match({routes: routes, location: currentUrl}, (err, redirect, props) => {
      if (err) {
        return reject(err)
      }
      return resolve(props)
    })
  })
}

export default async(req, res, next) => {
  const renderProps = await getMatchParams(routes, req.url)
  if (renderProps) {
    const component = (
      <RouterContext {...renderProps} />
    )
    req.body = await render(component)
    next()
  }
}
like image 224
Igor-Vuk Avatar asked Jun 09 '26 16:06

Igor-Vuk


1 Answers

Ok. I have found a problem. I was referring to the bundle and server rendered string with two separate <div>. Inside my app.js I was doing this

render(
    <Router history={browserHistory}>
      {routes}
    </Router>,
  document.getElementById('app')
)

Thats why I should have been sending the string to the template like this.

app.use(Express.static(path.join(__dirname, '../', 'dist')))

app.use(serverRenderer)
app.get('*', (req: Object, res: Object) => {
  res.render('index', {app: req.body})
})

And finally my views/index.js should look like this

<body>
  <div id="app"><%- app %></div>
  <script src="http://localhost:3001/bundle.js"></script>
</body>
like image 184
Igor-Vuk Avatar answered Jun 11 '26 21:06

Igor-Vuk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!