Как исправить `Внимание: текстовое содержимое не соответствует. Сервер: «Некоторые данные» Клиент: «Загрузка ...» ` - PullRequest
0 голосов
/ 10 января 2019

Я получаю эту ошибку при начальной загрузке моего приложения SSR: Warning: Text content did not match. Server: "SOME DATA" Client: "Loading..." Как инициализировать клиентскую часть приложения, не устанавливая флаг loading в true?

Я настраиваю SSR с реагированием, экспрессом и аполлоном. Я получаю правильно отрендеренный HTML с данными с сервера рендерера, но когда клиентский пакет загружается, он пытается повторно получить данные. Гидратация настроена, и все данные с сервера рендеринга вставляются в HTML-код страницы.

/ 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")
);

Я ожидаю, что клиентская часть приложения переопределит значения на стороне сервера и не вызовет флаг loading при начальной загрузке.

1 Ответ

0 голосов
/ 18 января 2019

Из документации react-apollo раздел Пропуск запросов для SSR представляет механизм, позволяющий разработчикам явно пометить компонент, чтобы он либо загружал данные для этого компонента на сервер , либо * 1005. * переводит компонент на сервере в состояние «загрузки».

Попробуйте следующее:

// 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>
...