Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning Prop `href` did not match. using react server-side-rendering

I am using react-router-dom and I am guessing that this is causing the problem, but I have no clue where to even start looking or how to fix it. I also am getting errors like Warning: Did not expect server HTML to contain a <nav> in <div>.

As I stated, I'm not really sure where to look so if you think there is certain code that would be helpful please let me know and I will post it. Otherwise, I can post my code that I use to do SSR.

EDIT: Exact error: Warning: Prophrefdid not match. Server: "/profile/5a073dc44cb45b00125e5c82" Client: "profile/5a073dc44cb45b00125e5c82"

I have checked the client and it has /profile/:id so not sure where it says there is not a /, as for the other error with the <nav> in <div> , I have a nav inside my header , but I'm not really sure how to go about "fixing" that.

import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import serialize from 'serialize-javascript';
import { Helmet } from 'react-helmet';
import { matchRoutes } from 'react-router-config';

import routes from './src/routes';
import createStore from './src/stores';

function handleRender(req, res) {
  let initial = {};

  if (req.vertexSession != null && req.vertexSession.user != null) {
    initial.user = { currentUser: req.vertexSession.user };
  }
  const store = createStore.configure(initial); // create Store in order to get data from redux

  const promises = matchRoutes(routes, req.path)
    .map(({ route, match }) => {
      // Matches the route and loads data if loadData function is there
      return route.loadData
        ? route.loadData(store)
        : route.loadDataWithMatch ? route.loadDataWithMatch(store, match) : null;
    })
    .map(promise => {
      if (promise) {
        return new Promise((resolve, reject) => {
          promise.then(resolve).catch(resolve); // lets all data load even if route fails
        });
      }
    });

  Promise.all(promises).then(() => {
    const context = {};
    if (context.url) {
      return res.redirect(301, context.url); // redirect for non auth users
    }

    if (context.notFound) {
      res.status(404); // set status to 404 for unknown route
    }
    const content = renderToString(
      <Provider store={store}>
        <StaticRouter location={req.path} context={context}>
          <div>{renderRoutes(routes)}</div>
        </StaticRouter>
      </Provider>
    );
    // console.log(store.getState());
    const initialState = serialize(store.getState());

    const helmet = Helmet.renderStatic();

    res.render('index', { content, initialState, helmet });
  });
}

module.exports = handleRender;
like image 226
Taylor Austin Avatar asked Nov 16 '17 18:11

Taylor Austin


3 Answers

Did you fix this already? I had the similar problem with my react app and fixed it. Here was my problem:

<Link to="./shop">Shop</Link>

my fix:

<Link to="/shop">Shop</Link>

Whatever you are rendering with the server is the issue. I suggest to comb through your routes module and see if you forgot a forward slash somewhere. If that doesn't work look at through the components your importing in the routes file.

like image 109
Kevorkian Avatar answered Nov 13 '22 07:11

Kevorkian


To add to Kevorkian answer:

Make sure to prefix all the routes with a /

Note the /update

<Link href={{ pathname: '/update', query: { id: product.id } }}>
like image 44
Bar Horing Amir Avatar answered Nov 13 '22 07:11

Bar Horing Amir


This happened to me in nextjs. It was because i had something like Link=/auth/${isLogin?"sign-up":"login"}. This was an issue because there is no reference at compile time. The should have been isLogin ? "/auth/sign-up" : "/auth/login"}

like image 21
Chijioke Okafor Avatar answered Nov 13 '22 09:11

Chijioke Okafor