エンジニアの覚え書き

web系エンジニアの技術メモを主に投稿していきます。

ReactDOM.hydrateの仕様を少し理解した

reactjs.org

React expects that the rendered content is identical between the server and the client. It can patch up differences in text content, but you should treat mismatches as bugs and fix them. In development mode, React warns about mismatches during hydration. There are no guarantees that attribute differences will be patched up in case of mismatches. This is important for performance reasons because in most apps, mismatches are rare, and so validating all markup would be prohibitively expensive.

意訳すると、htmlの要素の差異は警告を出力して修正するが、htmlの属性の差異はパフォーマンスの都合で修正される保証はない、とのことらしい。 localStorageにtokenがあれば自動で認証して画面表示するようなページで、React16にバージョン上げてからレイアウト崩れる不具合はこれが原因だった(特定の要素のclassの値が期待通りにならなくて困っていた)。

以前の修正

client.js

リダイレクトする前にinnerHTMLを空にする方法(この修正だと一部の画面では不具合が修正されなかった)。

    if (route.redirect) {
      history.replace(route.redirect);
      // const container: Element = (document.getElementById('app'): any);
      ReactDOM.unmountComponentAtNode(container);
      container.innerHTML = '';
      return;
    }

今回の修正

SomeComponent

componentDidMountが実行されたタイミングでstateを変えてレンダリングする方法(これで修正できた)。

type StateTypes = {|
  isMounted: boolean,
|};
class SomeComponent extends React.Component<PropTypes, StateTypes> {
  constructor(props: PropTypes) {
    super(props);
    this.state = { isMounted: false };
  }

  componentDidMount() {
    this.setState({ isMounted: true });
  }

  render() {
    const { isMounted } = this.state;

    return isMounted ? (
      // レンダリングしたいコンポーネント
    ) : (
      // loadingとか表示する
    );
  }
}