Jest无法正确识别navHeading props报错,如何修复?
问题原因
你遇到的警告是因为:navHeading是你给Styled Components定义的自定义prop,但Styled Components默认会把所有未处理的props传递给底层的Material-UI Typography组件,而Typography最终会渲染成原生DOM元素(如<h1>、<p>)。React会校验原生DOM元素的props,不识别的navHeading就会触发警告——开发环境可能因为Styled Components的优化没显示,但Jest测试时会暴露这个问题。
下面是几种可行的解决方法:
方法1:使用Styled Components的Transient Props(推荐)
Styled Components支持临时属性(Transient Props),在prop名前加$前缀,这样它只会被Styled Components使用,不会传递给底层DOM元素或组件。
修改步骤:
更新StyledComponents.js:
将所有props.navHeading改为props.$navHeading:// StyledComponents.js import { withTheme } from "@material-ui/core/styles"; import { Typography } from "@material-ui/core"; import styled from 'styled-components'; const StyledTypography = withTheme(styled(Typography).attrs((props) => ({ }))` ${(props) => { if (props.$navHeading) return `SOME TEXT` }} `); export {StyledTypography};更新Navbar.js:
传递prop时加上$前缀:// Navbar.js import { StyledTypography } from "./StyledComponents"; class NavBar extends React.Component { render(){ return ( <> <StyledTypography $navHeading> HELLO WORLD </StyledTypography> </> ) } }
这样$navHeading只会被Styled Components的样式逻辑读取,不会传递给底层的DOM元素,自然就不会触发React的警告。
方法2:手动过滤自定义Prop
如果你不想修改prop名称,可以在Styled Components中手动过滤掉navHeading,只把其他props传递给底层的Typography组件。
修改StyledComponents.js:
// StyledComponents.js import { withTheme } from "@material-ui/core/styles"; import { Typography } from "@material-ui/core"; import styled from 'styled-components'; const StyledTypography = withTheme(styled(({ navHeading, ...props }) => ( <Typography {...props} /> ))` ${(props) => { if (props.navHeading) return `SOME TEXT` }} `); export {StyledTypography};
这里通过解构把navHeading从props中剥离,只传递剩余的props给Typography组件,避免了自定义prop流向DOM元素。
方法3:测试时忽略警告(临时方案)
如果以上方法都无法快速实施,可以在Jest的配置中忽略这个特定警告。
在你的Jest setup文件(比如src/setupTests.js)中添加:
// 过滤React不识别DOM prop的警告 const originalError = console.error; beforeAll(() => { console.error = (...args) => { if (/React does not recognize the `navHeading` prop on a DOM element/.test(args[0])) { return; } originalError.call(console, ...args); }; }); afterAll(() => { console.error = originalError; });
这种方法只是隐藏警告,并没有从根源解决问题,不推荐长期使用。
内容的提问来源于stack exchange,提问作者Aditya Kumar

