Next.JS:警告期望服务器HTML在<div>中包含匹配的<a>;如何补水?

时间:2019-10-08 20:19:54

标签: reactjs next.js server-side-rendering isomorphic-javascript rehydratration-in-react-nextjs

我正在使用Semantic-UI React和Next.JS,但它出现在<768px的断点处,我的Home组件在刷新浏览器时完全中断。我知道,因为它是react / next.js应用程序,所以他们负责路由,但是我想我想知道如果用户碰巧会这样做吗?

在我的/ login,/ register或/ profile路由上不会发生

因此,我已经检查过以解决我的问题-Here,在该帖子中它指向React docs;为什么会发生这种情况的说明以及解决方案似乎都不适合我的情况。

  

与render()相同,但用于水化其HTML的容器   内容由ReactDOMServer呈现。 React将尝试附加   现有标记的事件监听器。

     

React期望渲染的内容在   服务器和客户端。它可以弥补文本内容的差异,   但您应将不匹配项视为错误并加以修复。开发中   模式下,React会警告有关水合过程中的不匹配情况。没有   确保在发生以下情况时可以修补属性差异   不匹配。由于性能原因,这一点很重要,因为在大多数情况下   应用程序,不匹配的情况很少发生,因此验证所有标记将是   太贵了。

     

如果不可避免地要使用单个元素的属性或文本内容   服务器和客户端之间的差异(例如,   时间戳记),您可以通过添加以下内容使警告静音   对元素的抑制HydrationWarning = {true}。它只工作一个   高度较深,旨在用作逃生舱口。不要过度使用它。   除非是文本内容,否则React仍然不会尝试对其进行修补,因此   它可能会保持不一致,直到将来进行更新。

     

如果您有意在服务器上渲染其他内容   和客户端,您可以进行两遍渲染。组成部分   在客户端上呈现不同的内容可以读取状态变量   像this.state.isClient,您可以在其中将其设置为true   componentDidMount()。这样,初始渲染过程将渲染   与服务器相同的内容,避免不匹配,但另外一个   补水后会立即同步通过。

这是入口点文件:pages/index

import React from 'react'
import Head from '../components/head'
import HomeLayout from '../components/Home/Home.jsx'
import 'semantic-ui-css/semantic.min.css'
import '../styles/styles.scss'
import { connect } from 'react-redux'

// import {bindActionCreators} from 'redux'
// import withRedux from 'next-redux-wrapper'
import { logInUser } from '../store'


class Home extends React.Component {
    static async getInitialProps({ isLoggedIn }) {
        return { isLoggedIn }
    }


    render() {
        const { isLoggedIn } = this.props
        return (
        <div>
        {console.log("isLoggedIn ", isLoggedIn)}
           <Head title = 'Home' />
           <HomeLayout isLoggedIn = { isLoggedIn }/>
        </div>
        )
    }
}




export default connect(state => state)(Home);

这是我的pages/_app

import React from 'react'
import { Provider } from 'react-redux'
import App from 'next/app'
import withRedux from 'next-redux-wrapper'
import { initializeStore } from '../store'

export default withRedux(initializeStore)(
 class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
   return {
    pageProps: Component.getInitialProps
     ? await Component.getInitialProps(ctx)
     : {}
   }
  }

  render() {
   const { Component, pageProps, store } = this.props
   return (
    <Provider store={store}>
     <Component {...pageProps} />
    </Provider>
   )
  }
 }
)

任何帮助

2 个答案:

答案 0 :(得分:1)

发生这种情况的原因是您渲染的页面很可能是静态生成的。在 React 中,当您使用 ReactDOM.rehydrate 时,通常会发生这种情况,最好的方法是使用 ReactDOM.render。

然而,对于 Nextjs,无论是使用服务器端渲染还是静态生成,都会在服务器上渲染整个 HTML,或者分别存储在服务器上。因此,当您尝试以任何方式渲染组件以根据客户端渲染组件时,都会弹出。

要摆脱这种情况,您可以使用 ClientOnly 包装器组件来包装需要在客户端完成的任何事情。

import { useEffect, useState } from 'react';

interface Props {
  children: any;
}

const ClientOnly: React.FC<Props> = ({ children, ...delegated }) => {
  const [hasMounted, setHasMounted] = useState(false);

  useEffect(() => {
    setHasMounted(true);
  }, []);

  if (!hasMounted) {
    return null;
  }

  return <div {...delegated}>{children}</div>;
};
export default ClientOnly;

以下是一些关于以下内容的资源:

所以你所要做的就是用以下方式包装客户端的组件:

// below statement is dependent on the client but the page is static
const isDesktopCommonOrAbove = useMediaQuery({ minWidth: 1366 });

/* ...other stuff... */

// Returned JSX
<div>
    <ClientOnly>{isDesktopCommonOrAbove ? <div className={styles.board} /> : null}</ClientOnly>
</div>

答案 1 :(得分:0)

大多数情况下,这是由于缺少结束标记/括号造成的。

在nextJS上,如果您使用的是<style jsx>,则可能是您的某些班级没有正确地用方括号括起来或属性缺少分号。

例如下面的代码将给您同样的警告。

不正确:

<style jsx>`{ // missing closing bracket
   div {
     background: #fff;

}`</style>

正确:

<style jsx>`{
    `div {
      background: #fff;
     }
}`</style>

请查看目标组件中导入的依赖项/组件,您可能遇到类似的问题。