반응 + 재료 UI - 경고: Prop className이 일치하지 않습니다.
classNames가 다르게 할당되어 있어 Material-UI 컴포넌트 스타일의 클라이언트 측 렌더링과 서버 측 렌더링의 차이가 있습니다.
페이지를 처음 로드할 때는 classNames가 올바르게 할당되지만 페이지를 새로 고친 후에는 classNames가 일치하지 않게 되어 컴포넌트의 스타일이 없어집니다.콘솔에 표시되는 오류 메시지는 다음과 같습니다.
:: " " "
className
일치하지 않습니다.서버: "MuiFormControl-root-3 MuiFormControl-marginNormal-4 SearchBar-textField-31" 클라이언트: "MuiFormControl-root-3 MuiFormControl-marginNormal-4 SearchBar-TextField-2"
Material-UI TextField의 문서와 그에 부수되는 Code Sandbox의 예를 살펴보았지만 서버와 클라이언트의 classNames의 차이점을 찾을 수 없습니다.
삭제 'x' 아이콘이 있는 Material-UI Chips를 추가했을 때도 같은 문제가 발생하였습니다.새로 고침 후 1024px의 엄청난 너비로 렌더링된 'x' 아이콘입니다.같은 근본적인 문제는 아이콘이 올바른 스타일링 클래스를 수신하지 않았다는 것입니다.
스택 오버플로우에서는 클라이언트와 서버가 classNames를 다르게 렌더링하는 이유에 대해 몇 가지 질문이 있습니다(예를 들어 @Material-UI/core 버전 ^1.0.0으로 업그레이드하여 커스텀 server.js를 사용하고 setState에서 Math.random을 사용해야 합니다).이러한 질문들은 모두 해당되지 않습니다.
Github의 논의가 도움이 될지는 모르겠지만, 그들이 Material-UI의 베타 버전을 사용하고 있었기 때문에 도움이 되지 않을 것 같습니다.
재현을 위한 최소 절차:
프로젝트 폴더를 만들고 노드 서버를 시작합니다.
mkdir app
cd app
npm init -y
npm install react react-dom next @material-ui/core
npm run dev
패키지를 편집합니다.json:
에 추가: '스크립트' 추가:"dev": "next",
app/pages/index.dex:
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/컴포넌트/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)
의 [Visit]localhost:3000
이치노
브라우저를 새로 고치고 다음을 확인합니다.
TextField 주변의 빨간색 테두리가 사라집니다.
관련 립스:
- '표준' : 16.4.0
- "dom" : 16.4.0
- '다음' : 6.0.3
- "@material-ui/core" : 1.2.0
문제는 Next.js의 SSR 렌더링으로, 페이지가 렌더링되기 전에 스타일 조각이 생성됩니다.
와 Next하고 있는 ), Material UI라는 파일을 합니다.Next.js 파일을 합니다._document.js
제를해해 해해해다다
된 ★★★★_document.js
(여기에 제시된 바와 같이):
import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheets } from '@material-ui/styles'; // works with @material-ui/core/styles, if you prefer to use it.
import theme from '../src/theme'; // Adjust here as well
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
{/* Not exactly required, but this is the PWA primary color */}
<meta name="theme-color" content={theme.palette.primary.main} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with server-side generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
// Resolution order
//
// On the server:
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. document.getInitialProps
// 4. app.render
// 5. page.render
// 6. document.render
//
// On the server with error:
// 1. document.getInitialProps
// 2. app.render
// 3. page.render
// 4. document.render
//
// On the client
// 1. app.getInitialProps
// 2. page.getInitialProps
// 3. app.render
// 4. page.render
// Render app and page and get the context of the page with collected side effects.
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
};
};
이 문제는 ID가 포함된 다이내믹클래스 이름을 사용하는 MUI와 관련되어 있습니다.서버측에서 렌더링된 CSS의 ID가 클라이언트측 CSS와 동일하지 않기 때문에 미스매치 에러가 발생합니다.MUI SSR 문서를 읽는 것이 좋습니다.
nextjs에 이 문제가 있는 경우(저와 마찬가지로) MUI 팀이 제공하는 예를 따르십시오.Material-ui/examples/nextjs는 다음 URL에서 확인할 수 있습니다.
가장 중요한 부분은 "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-material-ui/mui/15073
서버측 렌더링 스타일시트를 삭제하고 렌더링된 새 클라이언트측으로 대체합니다.
문제는 서버 측에서 클래스 이름을 생성하지만 스타일시트는 자동으로 HTML에 포함되지 않는다는 것입니다.서버 측에서 렌더링된 컴포넌트에 대해 명시적으로 CSS를 추출하여 UI에 추가해야 합니다.자세한 내용은 https://material-ui.com/guides/server-rendering/ 를 참조해 주세요.
또 다른 중요한 문제가 있습니다.Material UI V4는 React Strict Mode와 호환되지 않습니다.Emotion 스타일 엔진을 채택한 버전 5에서는 엄격한 모드 호환성이 예정되어 있습니다.
그때까지 Respect Strict 모드를 디세블로 해 주세요.Next.js를 사용하는 경우 다음을 사용하여 앱을 만든 경우 기본적으로 설정됩니다.create-next-app
.
// next.config.js
module.exports = {
reactStrictMode: false, // or remove this line completely
}
Next.js와 스타일 컴포넌트, Babel에 의한 번역에서도 같은 문제가 있었습니다.실제로 클래스 이름은 클라이언트와 서버 측에서 다릅니다.
.babelrc에 기재하여 수정합니다.
{
"presets": ["next/babel"],
"plugins": [
[
"styled-components",
{ "ssr": true, "displayName": true, "preprocess": false }
]
]
}
이 문제는 Material-ui V5에서 발생하였습니다.이 문제를 해결하기 위한 해결책은 클래스 이름 생성기가 서버와 클라이언트에서 동일하게 동작하도록 하는 것입니다.따라서 _app.js에 다음 코드를 추가합니다.
import { StylesProvider, createGenerateClassName } from '@mui/styles';
const generateClassName = createGenerateClassName({
productionPrefix: 'c',
});
export default function MyApp(props) {
return <StylesProvider generateClassName={generateClassName}>...</StylesProvider>;
}
// 1 . Warning: prop classname did not match. Material ui with React Next.js
// 2 . Use your customization css here
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
title: {
flexGrow: 1,
},
my_examle_classssss: {
with: "100%"
}
}));
// 3 . Here my Component
const My_Example_Function = () => {
const classes = useStyles();
return (
<div className={classes.root}>
<Container>
<Examle_Component> {/* !!! Examle_Component --> MuiExamle_Component*/}
</Examle_Component>
</Container>
</div>
);
}
export default My_Example_Function
// 4. Add name parameter to the makeStyles function
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
title: {
flexGrow: 1,
},
my_examle_classssss: {
with: "100%"
},
}), { name: "MuiExamle_ComponentiAppBar" });
{/* this is the parameter you need to add { name: "MuiExamle_ComponentiAppBar" } */ }
{/* The problem will probably be resolved if the name parameter matches the first className in the Warning: you recive..
EXAMPLE :
Warning: Prop `className` did not match.
Server: "MuiSvgIcon-root makeStyles-root-98"
Client: "MuiSvgIcon-root makeStyles-root-1"
The name parameter will be like this { name: "MuiSvgIcon" }
*/ }
저는 이 불일치 사례를 공유하고 싶습니다.
경고: next-dev.js? 3515:32 경고: " " "
className
일치하지 않습니다.서버: "MuiButton-root MuiIconButton-root PrivateSwitchBase-12 MuiSwitch-colorSecondary" 클라이언트: "MuiButtonBase-root MuiSwitch-colorSecondary"
클라이언트에는 2개의 클래스가 더 있습니다.이것은 클라이언트측의 동작이 다르다는 것을 의미합니다.이 경우 이 구성요소는 서버 측에서 렌더링하지 않습니다.해결책은 이 컴포넌트를 동적으로 렌더링하는 것입니다.
export default dynamic(() => Promise.resolve(TheComponent), { ssr: false });
클라이언트와 서버의 classNames가 다른데 문제가 있었습니다.React, Material-UI, makeStyles 및 SSR(서버 사이드 렌더링)을 사용하고 있었습니다.오류:
Warning: Prop `className` did not match. Server: "jss3" Client: "App-colNav-3"
클라이언트와 서버의 Web pack 모드가 일치하지 않는 것을 깨닫기까지 몇 시간이 걸렸습니다.의 스크립트package.json
"devServer": "webpack --config webpack.server.config.js --mode=production --watch",
"devClient": "webpack --mode=development --watch",
내가 둘 다 바꾸면development
는 해결되었습니다 mode, "mode" 입니다. : )
"devServer": "webpack --config webpack.server.config.js --mode=development --watch",
"devClient": "webpack --mode=development --watch",
만약 누군가가 위의 해결책을 시도했는데도 여전히 어려움을 겪고 있다면, 이것을 시도해 보세요.
- 「 」를 경우
noSsr
컴포넌트나 테마의 어느쪽이든 프로포트를 제거합니다.
mui에서는 다음과 같은 설정을 하고 있었습니다.theme
오브젝트, 이것이 이 문제의 원인입니다.
import { createTheme, responsiveFontSizes } from "@mui/material/styles";
let theme = createTheme({
components: {
MuiUseMediaQuery: {
defaultProps: {
noSsr: true,
},
},
},
palette: {
mode: "light",
common: {
black: "#000",
white: "#fff",
},
primary: {
main: "#131921",
contrastText: "#fff",
},
secondary: {
main: "#fb6a02",
contrastText: "#fff",
}
}
})
- 중
noSSr
클라이언트와 서버의 스타일 불일치를 포함한 앱의 모든 문제를 해결했습니다.
이 문제는 Nextjs 서버 측 렌더링이 원인입니다.해결하기 위해 다음과 같이 합니다.
- 클라이언트 측에서 검출할 컴포넌트를 만듭니다.
import { useState, useEffect } from "react";
interface ClientOnlyProps {}
// @ts-ignore
const ClientOnly = ({ children }) => {
const [mounted, setMounted] = useState<boolean>(false);
useEffect(() => {
setMounted(true);
}, []);
return mounted ? children : null;
};
export default ClientOnly;
- 를 사용하여 내 페이지 구성 를 래핑합니다.
ClientOnly
표시
export default function App() {
return (
<ClientOnly>
<MyOwnPageComponent>
</ClientOnly>
);
}
클라이언트측인 경우는, 페이지상에 컴포넌트만을 렌더링 합니다. 현재 측에서 온 .<MyOwnPageComponent>
아무것도 하지
이 문제는 클라이언트 측 코드와 서버 측 웹 팩의 컴파일 모드가 다르기 때문에 발생했습니다.클라이언트의 번들은 "실가동" 모드를 사용하여 웹 팩에 의해 생성되었으며 서버는 "개발"용으로 최적화된 패키지에서 SSR 코드를 실행했습니다.이로 인해 generateAnd의 스타일 컴포넌트에 다른 "className" 해시가 생성되었습니다.Inject Styles():
if (process.env.NODE_ENV !== 'production') dynamicHash = phash(dynamicHash, partRule + i);
그래서 제 수정은 웹 팩 모드를 맞추는 것이었습니다.
을 붙일 수 있는 곳은 수 .makeStyles
이렇게요.
const useStyles = makeStyles({
card: {
backgroundColor: "#f7f7f7",
width: "33%",
},
title: {
color: "#0ab5db",
fontWeight: "bold",
},
description: {
fontSize: "1em"
}
}, { name: "MuiExample_Component" });
어떻게 동작하는지는 모르지만, 여기서 찾았습니다.경고: Prop 'className'이 일치하지 않습니다.재로드 시 Material UI css가 임의로 중단됩니다.
저도 NextJS + MUI v5를 사용하고 있는데 Git 브랜치를 병합한 직후에 이 오류가 발생했습니다.병합으로 인해 캐시의 무언가가 손상된 것 같습니다..next/의 내용을 삭제하고 dev 서버를 재부팅하면 오류가 사라집니다.
@Leonel Sanches da Silva의 답변은 그다지 효과가 없었지만, 다른 (비소재 UI) 프로젝트에서 발견한 단편들을 사용하면 충분히 효과가 있었던 것 같습니다.
dev.to의 Raul Sanchez에게 이 질문에 대한 답을 알려드립니다.
다음 검색 안 함styled-components
서버의 스타일을 변경하려면 이 페이지를 다음에 추가해야 합니다.pages/_document.js
:
import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}
}
이 코드는 업데이트될 수 있으므로 Next의 예에서 최신 정보를 확인하십시오.
언급URL : https://stackoverflow.com/questions/50685175/react-material-ui-warning-prop-classname-did-not-match
'sourcecode' 카테고리의 다른 글
SQL Server SELECT to JSON 함수 (0) | 2023.03.20 |
---|---|
게시 날짜를 저장하기 위해 두 열을 사용하여 Wordpress를 누르는 이유 (0) | 2023.03.20 |
jquery 응답 유형을 체크하는 방법. (0) | 2023.03.20 |
Twitter api 텍스트 필드 값이 잘렸습니다. (0) | 2023.03.20 |
'NodeModule'.ts(2339) 유형에 'hot' 속성이 없습니다. (0) | 2023.03.20 |