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

11,618

Solution 1

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>

Solution 2

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: "..."
Share:
11,618
rreckonerr
Author by

rreckonerr

Updated on June 05, 2022

Comments

  • rreckonerr
    rreckonerr almost 2 years

    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.

  • Fortune
    Fortune over 2 years
    This solved the problem for me