React+styled-components实现展开功能时出现expanded属性DOM错误警告
场景与问题
使用React 18.2.0、styled-components 6.1.8结合react-slick实现轮播图描述的“查看更多”功能,点击按钮切换文本截断状态时,遇到两个问题:
- styled-components警告:未知属性
expanded被传递到DOM - React警告:非布尔属性
expanded收到false值
现有代码实现
组件代码
import { useState } from 'react'; import Slider from 'react-slick'; import styled from 'styled-components'; import PropTypes from 'prop-types'; import 'slick-carousel/slick/slick.css'; import 'slick-carousel/slick/slick-theme.css'; function ReviewSlider({ list }) { const [expandedIndex, setExpandedIndex] = useState(null); const settings = { dots: true, infinite: true, speed: 500, slidesToShow: 1, slidesToScroll: 1, autoplay: false, }; const handleToggleExpand = (index) => { setExpandedIndex(expandedIndex === index ? null : index); }; ReviewSlider.propTypes = { list: PropTypes.arrayOf( PropTypes.shape({ description: PropTypes.string.isRequired, }) ).isRequired, }; return ( <Slider {...settings}> {list.map((item, index) => ( <div key={index}> <Description expanded={index === expandedIndex}> {item.description} </Description> {item.description.length > 200 && ( <ReadMoreButton onClick={() => handleToggleExpand(index)}> {expandedIndex === index ? 'Read Less' : 'Read More'} </ReadMoreButton> )} </div> ))} </Slider> ); }
styled-components定义
const Description = styled.p` margin: 8px 0; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: ${({ expanded }) => (expanded ? 'unset' : '5')}; -webkit-box-orient: vertical; transition: -webkit-line-clamp 0.5s ease-in-out; `; const ReadMoreButton = styled.button` background: none; border: none; color: #525252; cursor: pointer; font-weight: bold; margin: 8px 0; padding: 0; outline: none; font-size: 16px; `;
控制台提示
styled-components警告
styled-components: it looks like an unknown prop "expanded" is being sent through to the DOM, which will likely trigger a React console error. If you would like automatic filtering of unknown props, you can opt-into that behavior via
<StyleSheetManager shouldForwardProp={...}>(connect an API like@emotion/is-prop-valid) or consider using transient props ($prefix for automatic filtering.)
React属性错误
Warning: Received
falsefor a non-boolean attributeexpanded.
If you want to write it to the DOM, pass a string instead: expanded="false" or expanded={value.toString()}.
If you used to conditionally omit it with expanded={condition && value}, pass expanded={condition ? value : undefined} instead.
解决方案
问题根源是styled-components会把未标记的自定义属性传递给底层DOM元素,而expanded不是原生HTML标签的合法属性。使用瞬态属性即可解决,只需给自定义属性添加$前缀:
- 修改styled-components的
Description组件,将props中的expanded改为$expanded:
const Description = styled.p` margin: 8px 0; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: ${({ $expanded }) => ($expanded ? 'unset' : '5')}; -webkit-box-orient: vertical; transition: -webkit-line-clamp 0.5s ease-in-out; `;
- 在组件中使用
Description时,传递$expanded属性:
<Description $expanded={index === expandedIndex}> {item.description} </Description>
瞬态属性会被styled-components自动过滤,不会传递到DOM元素上,同时能正常用于样式逻辑判断,彻底解决两个警告问题。
内容的提问来源于stack exchange,提问作者Ermin

