Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix `Warning: Text content did not match. Server: "Some Data" Client: "Loading..."`

I'm getting this error on initial load of my SSR application: Warning: Text content did not match. Server: "SOME DATA" Client: "Loading..." How to initialize client side of the app without setting loading flag to true?

I’m setting up a SSR with react, express and apollo. I get a properly rendered HTML with data from the renderer server, but when client bundle loads up it’s trying to refetch data. Hydration is set up and all the data from renderer server is injected into the HTML of the page.

/index.js

<Query query={GET_USERS} variables={queryVariables}>
    {({
        loading,
        error,
        data
    }) => {
        if (loading) return <p>Loading...</p>;
        if (error) return `Error: ${error}`;
        return data.users.map(user => <p key={user.id}>{user.login}</p>);
    }}
</Query>

/renderer.js

export default async (req, client) => {
    const serverSideApp = (
        <ApolloProvider client={client}>
            <StaticRouter location={req.path} context={{}}>
                <div>{renderRoutes(RoutesList)}</div>
            </StaticRouter>
        </ApolloProvider>
    );
        return getDataFromTree(serverSideApp).then(() => {
            const content = renderToString(serverSideApp);

            return `
                  <html>
                      <head></head>
                      <body>
                          <div id="root">${content}</div>
                          <script src="bundle.js"></script>
                          <script>

    window.__APOLLO_STATE__=${serialize(client.extract())}
                          </script>
                      </body>
                  </html>
            `;
    })
};

/server.js

const app = express();

app.use(express.static("public"));

app.get("*", (req, res) => {
    const httpLink = createHttpLink({
        uri: "http://10.10.10.139:4000/",
        fetch
    });

    const client = new ApolloClient({
        link: httpLink,
        ssrMode: true,
        cache: new InMemoryCache()
    });

    renderer(req, client).then((html) => res.send(html));
});

app.listen(3000, () => {
    console.log("Server is up");
});

/client.js

const httpLink = createHttpLink({
    uri: "http://10.10.10.139:4000/"
});

const client = new ApolloClient({
    link: httpLink,
    cache: new InMemoryCache().restore(window.__APOLLO_STATE__)
});

ReactDOM.hydrate(
    <ApolloProvider client={client}>
      <BrowserRouter>
        <div>{renderRoutes(RoutesList)}</div>
      </BrowserRouter>
    </ApolloProvider>,
    document.getElementById("root")
);

I expect client side of the app rehydrate server side values and not to trigger loading flag on initial load.

like image 914
rreckonerr Avatar asked Jan 10 '19 15:01

rreckonerr


2 Answers

If using nextjs w/ styled-jsx https://github.com/vercel/styled-jsx this error can occur if you omit the jsx attribute on the style tag.

Good (jsx attribute is required):

<style jsx>{`...`}</style>

Bad (omit jsx attribute):

<style>{`...`}</style>

Omitting the jsx attr will throw following in browser Console:

react-dom.development.js Warning: Text content did not match. Server: "..." Client: "..."
like image 120
DeBraid Avatar answered Oct 27 '22 12:10

DeBraid


From react-apollo documentation, the Skipping queries for SSR section introduces a mechanism that allows developers to explicitly mark a component so that it either loads data for that component on the server or renders the component on the server in a 'loading' state.

Try the following:

// index.js

<Query query={GET_USERS} ssr={false} variables={queryVariables}>
    {({
        loading,
        error,
        data
    }) => {
        if (loading) return <p>Loading...</p>;
        if (error) return `Error: ${error}`;
        return data.users.map(user => <p key={user.id}>{user.login}</p>);
    }}
</Query>
like image 33
Peter Avatar answered Oct 27 '22 14:10

Peter