web-dev-qa-db-fra.com

React + Material-UI - Warning: Prop className did not match

Je rencontre des difficultés avec les différences entre le rendu côté client et côté serveur des styles dans les composants Material-UI en raison de l'attribution différente de classNames.

Les classNames sont attribués correctement lors du premier chargement de la page, mais après l'actualisation de la page, les classNames ne correspondent plus, de sorte que le composant perd son style. Voici le message d'erreur que je reçois sur la console:

Avertissement: Prop className ne correspond pas. Serveur: "MuiFormControl-root-3 MuiFormControl-marginNormal-4 SearchBar-textField-31 " Client: "MuiFormControl-root-3 MuiFormControl-marginNormal-4 SearchBar-textField-2 "

J'ai suivi le Material-UI TextField exemples de documents , et leur accompagnement exemple Code Sandbox , mais je n'arrive pas à comprendre ce qui cause la différence entre le serveur et classNames client.

J'ai rencontré un problème similaire lors de l'ajout de puces d'interface utilisateur avec une icône de suppression "x". L'icône 'x' rendue avec une largeur monstrueuse de 1024px après le rafraîchissement. Le même problème sous-jacent étant que l'icône ne recevait pas la classe correcte pour le style.

Il y a quelques questions sur Stack Overflow pour savoir pourquoi le client et le serveur peuvent afficher les noms de classe différemment (par exemple, besoin de mettre à niveau vers @ Material-UI/core version ^ 1.0.0, en utilisant un server.js personnalisé et en utilisant Math.random dans setState ), mais aucun de ces éléments ne s'applique dans mon cas.

Je ne sais pas assez pour dire si cette discussion Github pourrait aider, mais probablement pas car ils utilisaient une version bêta de Material-UI.

Étapes minimales pour reproduire:

Créez le dossier du projet et démarrez Node server:

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

modifier package.json:

Ajouter aux 'scripts': "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)

Visitez la page dans le navigateur localhost:3000 et voyez ceci:

bordure rouge autour du composant TextField

Actualisez le navigateur et voyez ceci:

Les styles du composant TextField ont dispar

Notez que la bordure rouge autour de TextField disparaît.

Libs pertinents:

  • "réagir": 16.4.0
  • "react-dom": 16.4.0
  • "suivant": 6.0.3
  • "@ material-ui/core": 1.2.0
11
David

Le problème est que le côté serveur génère les noms de classe mais les feuilles de style ne sont pas automatiquement incluses dans le HTML. Vous devez extraire explicitement le CSS et l'ajouter à l'interface utilisateur pour les composants rendus côté serveur. L'ensemble du processus est expliqué ici: https://material-ui.com/guides/server-rendering/

1
Dhana Krishnasamy