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

5

21

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;
Fang answered 16/11, 2017 at 18:19 Comment(0)
S
28

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.

Snipes answered 13/12, 2017 at 7:47 Comment(0)
P
13

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 } }}>
Pyrex answered 11/3, 2021 at 9:25 Comment(0)
D
2

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"}

Daffodil answered 24/2, 2022 at 15:23 Comment(0)
E
0

This happened to me in a React/Next project because of next links.

This is the component

const Breadcrumb = (props) => {
  return (
    <Row>
      <Col xs="12">
        <div className="page-title-box d-sm-flex align-items-center justify-content-between">
          <h4 className="mb-0 font-size-18">{props.breadcrumbItem}</h4>
          <div className="page-title-right">
            <ol className="breadcrumb m-0">
              <BreadcrumbItem>
                <Link href="#">{props.title}</Link>
              </BreadcrumbItem>
              <BreadcrumbItem active>
                <Link href="#">{props.breadcrumbItem}</Link>
              </BreadcrumbItem>
            </ol>
          </div>
        </div>
      </Col>
    </Row>
  );
};

Here we have Link href="#" (This is the server side)

<li class="breadcrumb-item">
  <a href="/search?searchTerm=a00&amp;codeSets=1%2C2%2C3%2C4%2C5%2C6%2C7#">Home
  </a>
</li>

After the page loaded, it becomes something like that above (This is the client side)

So we have a mismatch here in the DOM and we get this warning

SOLUTION

I was rendering this component on my pages and getting this warning. As a solution, i have implemented dynamic content approach checking some state values before rendering the element.

For instance in my code detail page, I have done that like below.

const CodeDetail = (props) => {
    const [code, setCode] = useState<any>(null);

    useEffect(() => {
        if (props.router.query.code) {
            if (codesData.filter(codeData => codeData.code == props.router.query.code).length > 0) {
                setCode(codesData.find(codeData => codeData.code == props.router.query.code));
            }
            else {
                setCode({});
            }
        }
    }, [props.router]);

    let pageContent;

    if (code !== null) {
        pageContent = (<Container fluid={true}><Breadcrumbs title="Codes" breadcrumbItem="Code Detail" /></Container>)
    }
    else {
        pageContent = null;
    }

    return(
        <React.Fragment>{pageContent}</React.Fragment>
    );
};
Embolus answered 31/3, 2022 at 6:33 Comment(0)
C
0

I just want to chip in that with Next's Link component it NOT will accept an empty string for an href property like it does in native HTML. If you really want a link that links to nowhere you HAVE to use #. That's how I got my error.

Cetology answered 26/6, 2022 at 13:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.