React 16에서 hydrate ()와 render ()의 차이점은 무엇입니까?


86

문서를 읽었지만 React 16 hydrate()과 의 차이점을 실제로 이해하지 못했습니다 render().

hydrate()SSR과 클라이언트 측 렌더링을 결합하는 데 사용된다는 것을 알고 있습니다.

누군가가 수분 공급이 무엇인지 설명하고 ReactDOM의 차이점은 무엇입니까?


@tophar가 제공 한 아래 답변이 정확합니다. 더 자세히 알아 보려면이 reactjs.org/docs/react-dom.html을
Gorakh Nath

답변:


80

로부터 ReactDOMServer의 문서 (강조 광산) :

ReactDOM.hydrate()이 서버 렌더링 마크 업이 이미있는 노드에서 호출 하는 경우 React는이를 보존하고 이벤트 핸들러 만 연결 하므로 매우 우수한 첫로드 경험을 할 수 있습니다.

굵게 표시된 텍스트가 주요 차이점입니다. render초기 DOM과 현재 DOM 사이에 차이가있는 경우 노드를 변경할 수 있습니다. hydrate이벤트 핸들러 만 첨부합니다.

로부터 도입하는 것이 Github의 문제 hydrate별도의 API로 :

이것이 초기 DOM 인 경우 :

<div id="container">
    <div class="spinner">Loading...</div>
</div>

그리고 전화 :

ReactDOM.render(
   <div class="myapp">
      <span>App</span>
   </div>,
   document.getElementById('container')
)

클라이언트 측 전용 렌더링 (수화 아님)을 수행하려고합니다. 그런 다음 당신은

<div id="container">
   <div class="spinner">
       <span>App</span>
   </div>
</div>

속성을 패치하지 않기 때문입니다.

그들이 속성을 패치하지 않은 이유는

... 이것은 정상적인 수화 모드에서 수화하는 데 정말 느리고 비 SSR 트리로의 초기 렌더링 속도를 늦 춥니 다.


8
이해 해달라고 왜 렌더링 사업부 doesnot 유무 사업부와 클래스의 사용 이름 myapp와 이유가 회 전자 클래스 최종 렌더링 요소입니다
pravin의 poudel는

2
@pravinpoudel 클라이언트 측 렌더링 중에 속성을 패치하지 않기 때문이라고 생각합니다. 이것이 속성 class="spinner"<div>요소 에있는 그대로 유지되는 이유 입니다.
Glenn Mohammad

31

하이드레이트는 SSR (Server side Rendering)의 경우 기본적으로 사용됩니다. SSR은 서버에서 제공되는 스켈레톤 또는 HTML 마크 업을 제공하므로 페이지가 처음로드 될 때 비어 있지 않고 검색 엔진 봇이 SEO (SSR 사용 사례)에 대해 색인을 생성 할 수 있습니다. 따라서 hydrate는 JS를 페이지 또는 SSR이 적용되는 노드에 추가합니다. 페이지가 사용자가 수행 한 이벤트에 응답하도록합니다.

Render는 클라이언트 측 브라우저에서 컴포넌트를 렌더링하는 데 사용됩니다. 하이드레이트를 render로 바꾸려고하면 렌더링이 더 이상 사용되지 않으며 SSR의 경우 사용할 수 없다는 경고가 표시됩니다. 수화물에 비해 느리기 때문에 제거되었습니다.


23

나는.의 사용에 대해 위에서 말한 것에 추가 할 특정 사항이 hydrate없지만 그것에 대해 배우려고 노력하면서 약간의 예를 모았으므로 여기에 도움이되는 사람을위한 작업이 있습니다.

를 사용하는 페이지 ReactDOM.hydrateReactDOM.render. <script>태그 로로드되는 JSX로 작성된 일부 반응 구성 요소에 의존하며 , hydrate과 (와) 의 차이를 설명하기 위해 서버에 의해 인위적으로 지연됩니다 render.

기본 구조

  1. HTML "skeleton"이있는 파일 1 개
  2. JSX로 작성된 커스텀 React 구성 요소가있는 파일 1 개
  3. 서버가 사용할 모든 페이지를 생성하는 하나의 스크립트
  4. 서버를 실행하는 하나의 스크립트

결과

페이지를 생성하고 서버를 실행 한 후에 127.0.0.1는 헤더 수화물 , 버튼 및 두 개의 링크 로 이동하여 표시 됩니다. 버튼을 클릭 할 수 있지만 아무 일도 일어나지 않습니다. 잠시 후 문서로드가 완료되고 버튼이 클릭 수를 계산하기 시작합니다. 그런 다음 "렌더링"링크를 클릭합니다. 이제 내가 표시된 페이지에는 헤더 렌더링 과 두 개의 링크가 있지만 버튼은 없습니다. 잠시 후 버튼이 나타나고 즉시 반응합니다.

설명

"hydrate"페이지에서는 필요한 모든 html이 페이지와 함께 제공되기 때문에 모든 마크 업이 즉시 렌더링됩니다. 아직 연결된 콜백이 없기 때문에 버튼이 응답하지 않습니다. components.js로드가 완료 되면 에서 load이벤트가 발생 window하고 콜백이와 연결됩니다 hydrate.

'렌더링'페이지에서 버튼 마크 업은 페이지와 함께 제공되지 않고에 의해서만 삽입 ReactDOM.render되므로 즉시 표시되지 않습니다. 마지막으로로드되는 스크립트에 의해 페이지의 모양이 어떻게 부조리하게 변경되는지 확인하십시오.

출처

다음은 내가 사용중인 사용자 지정 반응 구성 요소입니다. 정적으로 구성 요소를 렌더링하는 데 반응하는 노드의 서버에서 사용되며 페이지에서 사용하기 위해 서버에서 동적으로로드됩니다 ( 파일 시작 부분에서 exportsReact개체를 확인하는 목적 임 ).

// components.jsx

var exports = typeof(exports) == 'object' ? exports : {};
var React = typeof(React) == 'object' ? React : require('react');

function MyButton(props) {
  [click, setClick] = React.useState(0);
  function handleClick() { setClick(click + 1); }
  return (
    <button onClick={handleClick}>Clicked: {click}</button>
  );
}

exports.MyButton = MyButton;

서버에 필요한 모든 페이지를 생성하는 데 사용되는 스크립트입니다. 먼저 babel을 사용하여 components.jsx를 javascript로 변환 한 다음 이러한 구성 요소를 React 및 ReactDOMServer와 함께 사용하여 실제 페이지를 만듭니다. 이러한 페이지는 다음과 같이 getPage파일에서 내 보낸 기능으로 생성됩니다 pageTemplate.js.

// genScript.js

let babel          = require('@babel/core');
let fs             = require('fs');
let ReactDOMServer = require('react-dom/server');
let React          = require('react');
let pageTemplate   = require('./pageTemplate.js');

script = babel.transformFileSync(
  'components.jsx', 
  {presets : [['@babel/react']]}
);

fs.writeFileSync('components.js',script.code);
let components = require('./components.js');

hydrateHTML = pageTemplate.getPage(
  'MyButton',
  ReactDOMServer.renderToString(React.createElement(components.MyButton)),
  'hydrate'
);

renderHTML = pageTemplate.getPage(
  'MyButton',
  '',
  'render'
);

fs.writeFileSync('hydrate.html',hydrateHTML);
fs.writeFileSync('render.html',renderHTML);

이 파일은 getPage이전에 언급 한 기능 만 내 보냅니다 .

// pageTemplate.js

exports.getPage = function(
  reactElementTag,
  reactElementString,
  reactDOMMethod
  ) {
  return `
  <!DOCTYPE html>
  <html>
    <head>
      <meta charset="utf-8" />
      <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js" defer></script>
      <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" defer></script>
      <script src="./components.js" defer></script>
    </head>
    <body> 
      <h1>${ reactDOMMethod }</h1>
      <div id="react-root">${ reactElementString }</div> 
      <a href="hydrate.html">hydrate</a>
      <a href="render.html">render</a>
    </body>
    <script>
      window.addEventListener('load', (e) => {
        ReactDOM.${ reactDOMMethod }(
          React.createElement(${ reactElementTag }),
          document.getElementById('react-root')
        );
      });
    </script>
  </html>
  `;
}

마지막으로 실제 서버

// server.js

let http = require('http');
let fs   = require('fs');

let renderPage       = fs.readFileSync('render.html');
let hydratePage      = fs.readFileSync('hydrate.html');
let componentsSource = fs.readFileSync('components.js');

http.createServer((req, res) => {
  if (req.url == '/components.js') {
    // artificial delay
    setTimeout(() => {
    res.setHeader('Content-Type','text/javascript');
    res.end(componentsSource);
    }, 2000);
  } else if (req.url == '/render.html') {
    res.end(renderPage);
  } else {
    res.end(hydratePage);
  }
}).listen(80,'127.0.0.1');

2
와. 기본적으로 질문에 답하고 Gatsby와 같은 최소 정적 생성기를 만드는 방법을 설명했습니다. 놀랄 만한. 정말 고마워!
Sergey Lukin

22

위에 추가로 ...

ReactDOM.hydrate()와 동일 render()하지만 ReactDOMServer에서 HTML 콘텐츠를 렌더링 한 컨테이너수화 (이벤트 리스너 첨부)하는 데 사용됩니다 . React는 이벤트 리스너를 기존 마크 업에 연결하려고합니다 .

서버 렌더링 컨테이너를 수화하기 위해 ReactDOM.render ()를 사용하는 것은 속도가 느려서 더 이상 사용되지 않으며 React 17 에서 제거 되므로 hydrate()대신 사용하십시오.


18

서버 측 React에서 이미 렌더링 된 HTML에 기능을 다시 넣는 전체 프로세스를 수화라고합니다.

따라서 한 번 렌더링 된 HTML을 다시 렌더링하는 프로세스를 수화라고합니다.

그래서 우리가 호출 ReactDOM.render()하여 우리의 응용 프로그램을 수화하려고하면 ReactDOM.hydrate().


1

render는 지정된 요소 (대부분의 경우 'root'로 명명 됨)의 모든 항목을 플러시하고 다시 빌드하는 반면, hydrate는 지정된 요소 내부에 이미있는 항목을 유지하고 그로부터 빌드하여 초기 페이지로드 속도를 높입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.