web-dev-qa-db-ja.com

React + Material-UI-警告:Prop classNameが一致しませんでした

ClassNamesの割り当てが異なるため、Material-UIコンポーネントのスタイルのクライアント側とサーバー側のレンダリングの違いに問題があります。

ClassNamesは最初のページのロード時に正しく割り当てられますが、ページを更新した後、classNamesは一致しなくなり、コンポーネントはそのスタイルを失います。これは、コンソールに表示されるエラーメッセージです。

警告:プロップclassNameが一致しませんでした。サーバー: "MuiFormControl-root-3 MuiFormControl-marginNormal-4SearchBar-textField-31"クライアント: "MuiFormControl-root-3 MuiFormControl-marginNormal-4 SearchBar-textField-2 "

Material-UI TextField example docs とそれに付随する Code Sandbox example をフォローしましたが、サーバーの違いの原因がわからないようですおよびクライアントのclassNames。

削除 'x'アイコンが付いたMaterial-UIチップを追加するときに、同様の問題が発生しました。リフレッシュ後、1024xの巨大な幅でレンダリングされた「x」アイコン。同じ根本的な問題は、そのアイコンがスタイリングの正しいクラスを受け取っていなかったことです。

Stack Overflowについて、クライアントとサーバーがclassNamesを異なる方法でレンダリングする可能性がある理由(たとえば、@ Material-UI/coreバージョン^ 1.0.0にアップグレードする必要がある、カスタムserver.jsを使用する、setStateでMath.randomを使用する)についていくつか質問があります。 )、しかしこれらのどれも私の場合には適用されません。

このGithubディスカッション が役立つかどうかはわかりませんが、Material-UIのベータ版を使用していたので、おそらく役に立ちません。

再現するための最小限の手順:

プロジェクトフォルダを作成し、Node server:

mkdir app
cd app
npm init -y
npm install react react-dom next @material-ui/core
npm run dev

package.jsonを編集します。

「スクリプト」に追加:"dev": "next",

app/pages/index.jsx:

import Head from "next/head"
import CssBaseline from "@material-ui/core/CssBaseline"
import SearchBar from "../components/SearchBar"

const Index = () => (
  <React.Fragment>
    <Head>
      <link
        rel="stylesheet"
        href="https://fonts.googleapis.com/css?family=Roboto:300,400,500"
      />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta charSet="utf-8" />
    </Head>
    <CssBaseline />
    <SearchBar />
  </React.Fragment>
)

export default Index

app/components/SearchBar.jsx:

import PropTypes from "prop-types"
import { withStyles } from "@material-ui/core/styles"
import TextField from "@material-ui/core/TextField"

const styles = (theme) => ({
  container: {
    display: "flex",
    flexWrap: "wrap",
  },
  textField: {
    margin: theme.spacing.unit / 2,
    width: 200,
    border: "2px solid red",
  },
})

class SearchBar extends React.Component {
  constructor(props) {
    super(props)
    this.state = { value: "" }
    this.handleChange = this.handleChange.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  handleChange(event) {
    this.setState({ value: event.target.value })
  }

  handleSubmit(event) {
    event.preventDefault()
  }

  render() {
    const { classes } = this.props
    return (
      <form
        className={classes.container}
        noValidate
        autoComplete="off"
        onSubmit={this.handleSubmit}
      >
        <TextField
          id="search"
          label="Search"
          type="search"
          placeholder="Search..."
          className={classes.textField}
          value={this.state.value}
          onChange={this.handleChange}
          margin="normal"
        />
      </form>
    )
  }
}

SearchBar.propTypes = {
  classes: PropTypes.object.isRequired,
}

export default withStyles(styles)(SearchBar)

ブラウザでページにアクセスlocalhost:3000そしてこれを見てください:

TextFieldコンポーネントの周りの赤い枠

ブラウザを更新してこれを見てください:

TextFieldコンポーネントのスタイルがなくなりました

TextFieldの周りの赤い境界線が消えていることに注意してください。

関連するライブラリ:

  • 「反応する」:16.4.0
  • 「リアクトドム」:16.4.0
  • 「次へ」:6.0.3
  • "@ material-ui/core":1.2.0
11
David

問題は、サーバー側がクラス名を生成するが、スタイルシートがHTMLに自動的に含まれないことです。 CSSを明示的に抽出し、サーバー側のレンダリングされたコンポーネントのUIに追加する必要があります。プロセス全体をここで説明します: https://material-ui.com/guides/server-rendering/

1