Mam trudności z różnicami między po stronie klienta i renderowania po stronie serwera stylów w składnikach materiałowych z powodu typów klasy przypisywanych inaczej.

Dotychczas są przypisane poprawnie przy pierwszym ładowaniu strony, ale po odświeżaniu strony, nazwy w klasie, więc komponent traci stylizacji. Jest to komunikat o błędzie, które odbieram na konsoli:

OSTRZEŻENIE: Prop className nie pasowało. Serwer: "MuiformControl-Root-3 MuiformControl-Marginnormal-4 SearchBar-TextField-31 " Klient: "MuiformControl-Root-3 MuiformControl-Marginnormal-4 SearchBar-TextField-2 "

Podążałem za materiałem-UI TextField przykładowe doktorzy i ich towarzysząca Przykład piaskownicy kodu, ale nie mogę dowiedzieć się, co powoduje różnicę między serwerem a nazwami klasy klienta.

Doświadczyłem podobnego problemu podczas dodawania wiórów materiałowych z ikoną Usuń "X". Ikona "X" świadczona z potworną szerokość 1024px po orzeźwieniu. Ta sama istotna kwestia była ta ikona nie otrzymywała prawidłowej klasy do stylizacji.

Istnieje kilka pytań dotyczących przepełnienia stosu adresowanie, dlaczego klient i serwer mogą renderować nazwy w klasyce inaczej (np. Wystarczy uaktualnić do @ Material-UI / Core Version ^ 1.0.0, za pomocą niestandardowego serwera.js i przy użyciu matematyki w Setstate ), ale żaden z nich nie ma zastosowania w moim przypadku.

Nie wiem wystarczająco dużo, by powiedzieć, czy Dyskusja Github może pomóc, Ale prawdopodobnie nie od czasu używania wersji beta materiału-ui.

Minimalne kroki do reprodukcji:

Utwórz folder projektu i uruchom serwer węzłów:

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

Edytuj pakiet.json:

Dodaj do "Skrypty": "dev": "next",

Aplikacja / strony / 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

Aplikacja / komponenty / 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)

Odwiedź stronę w przeglądarce localhost:3000 i zobacz to:

Czerwona obramowanie wokół komponentu TextField

Odśwież przeglądarkę i zobacz to:

Style komponentu TextField zniknęły

Zauważ, że czerwona obramowanie wokół textime znika.

Odpowiednie lib:

  • "Reaguj": 16.4.0
  • "React-Dom": 16.4.0
  • "Dalej": 6.0.3
  • "@ Material-Ui / Core": 1.2.0
13
David 4 czerwiec 2018, 19:41

3 odpowiedzi

Najlepsza odpowiedź

Problemem jest strona serwera generuje nazwy klas, ale arkusze stylów nie są automatycznie zawarte w HTML. Musisz jawnie wyodrębnić CSS i dołącz go do interfejsu użytkownika na stronie serwera świadczonych komponentów. Cały proces jest wyjaśniony tutaj: https://material-ui.com/guides/Server-rendering /.

5
Dhana Krishnasamy 24 wrzesień 2018, 14:50

Ten problem jest związany z MUI przy użyciu nazwy klasy dynamicznej, która zawiera identyfikator. Identyfikatory z serwera renderowane CSS nie są takie same jak CSS Client CSS, stąd błąd niedopasowania. Dobry początek jest czytanie MUI SSR Dokumentacja

Jeśli masz ten problem z NextJs (jak ja), podążaj za przykładem dostarczonym przez zespół MUI, który można znaleźć tutaj: Material-ui / przykłady / Nextjs

Najważniejsza część jest w "Przykłady / Nextjs / Pages / _App.js":

componentDidMount() {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector('#jss-server-side');
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
  }

Powiązany bilet można znaleźć tutaj: MUI-ORG / Material-Ui / problemy / 15073.

Co robi, jest usuń stronę serwera renderowaną arkusz stylów i zastąp go przez nową stronę klienta renderowanego

5
chrisweb 29 grudzień 2019, 16:54

Miałem ten sam problem z następnym.js i składnikiem w stylu, z dzielnicą Babel. Właściwie nazwy klas są różne na kliencie i stronie serwera.

Napraw go na piśmie w swoim .Babelrc:

{
"presets": ["next/babel"],
"plugins": [
    [
      "styled-components",
      { "ssr": true, "displayName": true, "preprocess": false }
    ]
]

}

3
pom421 30 październik 2019, 13:42