当前位置: 首页 > 知识库问答 >
问题:

React+Material-UI-警告:道具类名不匹配

马臻
2023-03-14

由于类名的分配不同,我对Material-UI组件中样式的客户端和服务器端呈现之间的差异感到困难。

第一次加载页面时,类名分配正确,但刷新页面后,类名不再匹配,因此组件失去其样式。这是我在控制台上收到的错误消息:

警告:道具classname不匹配。服务器:“MuiformControl-Root-3 MuiFormControl-marginNormal-4 SearchBar-TextField-31”客户端:“MuiformControl-Root-3 MuiFormControl-marginNormal-4 SearchBar-TextField-2”

我已经学习了Material-UI TextField示例文档及其附带的代码沙箱示例,但我似乎无法弄清楚是什么导致了服务器类名和客户端类名之间的差异。

在添加带有删除“X”图标的材质UI芯片时,我遇到了类似的问题。刷新后的“X”图标呈现出惊人的1024px宽度。同样的潜在问题是图标没有接收到正确的样式化类。

关于堆栈溢出,有几个问题可以解决客户端和服务器可能以不同方式呈现类名的原因(例如,需要升级到@Material-UI/Core版本^1.0.0,使用自定义server.js,并在setState中使用Math.random),但这些问题都不适用我的情况。

我不知道Github的讨论是否有帮助,但可能没有,因为他们使用的是beta版本的Material-UI。

创建项目文件夹并启动节点服务器:

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

添加到“脚本”:“dev”:“next”,

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
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
  • “React-DOM”:16.4.0
  • “下一个”:6.0.3
  • “@material-ui/core”:1.2.0

共有2个答案

水品
2023-03-14

这个问题与MUI使用包含ID的动态类名有关。服务器端呈现的CSS的ID与客户端CSS不相同,因此出现不匹配错误。阅读MUI SSR文档是一个好的开始

如果您在nextjs中遇到这个问题(和我一样),请遵循MUI团队提供的示例,可以在这里找到:material-ui/examples/nextjs

最重要的部分在“examples/nextjs/pages/_app.js”中:

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

相关票据见:mui-org/material-ui/issues/15073

它所做的是删除服务器端呈现的样式表,并用一个新的客户端呈现的样式表替换它

贺亦
2023-03-14

问题是服务器端生成类名,但样式表并不自动包含在HTML中。您需要显式提取CSS并将其附加到服务器端呈现组件的UI中。整个过程说明在这里:https://material-ui.com/guides/server-rendering/

 类似资料:
  • 问题内容: 由于classNames的分配方式不同,我在Material-UI组件中的客户端和服务器端样式渲染之间存在差异。 第一次加载页面时会正确分配className,但是刷新页面后,className将不再匹配,因此组件将失去其样式。这是我在控制台上收到的错误消息: 警告:道具不匹配。服务器:“ MuiFormControl-root-3 MuiFormControl- marginNorm

  • React Native Material UI (iOS and Android supported) Highly customizable material design components for React Native! Documentation Getting Started Usage Demo & Examples Components Showroom Savee.io i

  • 问题内容: 使用css-in-js方法将类添加到React组件,如何添加多个组件? 这是class变量: 这是我的用法: 上面的作品,但有没有办法添加两个类,而无需使用npm包?就像是: 问题答案: 您可以使用字符串插值:

  • 我想使用材料-UI Next文本字段道具链接,道具类型是。前一个版本的材料UI道具名称是,道具类型是链接。 以前的版本使用道具: 在先前版本的Material UI中使用,代码可以很好地显示错误状态。 Textfield材质界面下一步使用

  • 问题内容: 我在项目中一直使用这两个工具,有时我发现需要在Bootstrap组件和UI显示中使用Material UI组件,这与我期望的一样。有人建议我不要使用这种方法。既然两者都在使用网格并且可以灵活使用,那有什么理由吗? 问题答案: 我倾向于冗长,因此我将简洁的答案放在这里: 结论: 谁说不好用两者可能只是在表达自己的观点,实际上说不好用两者在设计时确实缺乏上下文。@ user3770494提

  • 我得到这个错误: index.js:1375警告:失败的道具类型:提供给的道具无效。 我在我的应用程序中使用了一个外部组件,它是从github获得的,可以在后台渲染视频。这里是链接。https://github.com/samAbeywickrama/reactjs-videobg 它与proptypes有关,但由于它的遗留和react建议使用flo,所以我根本不使用类型检查。