简体   繁体   中英

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: Prop href did not match. Server: "/profile/5a073dc44cb45b00125e5c82" Client: "profile/5a073dc44cb45b00125e5c82" did 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;

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.

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

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"} isLogin ? "/auth/sign-up" : "/auth/login"}

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>
    );
};

I just want to chip in that with Next's Link component it 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM