我一直在努力处理样式组件和瞬态道具。请参阅下面的代码。
StyledLabel
,它接收一个瞬态道具。StyledLabel
用于函数组件中,我们称之为IntermediateLabel
。IntermediateLabel
将收到的 props 传递给 StyledComponent
。IntermediateLabel
在样式化组件中重新设计了样式,我们称之为ExtraStyledLabel
现在问题来了,当将瞬态 prop 传递给
ExtraStyledLabel
时,它并没有传递给 IntermediateLabel
。但是直接使用 IntermediateLabel
时,它会传递给 StyledLabel
。
功能组件不能重新设计吗?是我做错了什么还是bug?
这是代码,Codepen https://codepen.io/tengl/pen/abxgzdL
const { createRoot } = ReactDOM;
const { useState, forwardRef } = React;
const { createGlobalStyle } = styled;
const GlobalStyle = createGlobalStyle`
html, body, #app {
height: 100%;
min-height: 100%;
}
`;
const App = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`;
const StyledLabel = styled.p`
color: ${(p) => (p.$isSelected ? "green" : "red")};
font-family: "Roboto Mono", monospace;
font-size: 20px;
`;
// WORKS
const IntermediateLabelStyled = styled(StyledLabel)``;
// WORKS
const IntermediateLabelComponent = forwardRef(({ children, ...props }) => {
console.log(props.$isSelected);
return <StyledLabel {...props}>{children} </StyledLabel>;
});
// WORKS
const IntermediateLabelForwardRef = ({ children, ...props }) => {
console.log(props.$isSelected);
return <StyledLabel {...props}>{children} </StyledLabel>;
};
// WORKS
const ExtraStyledLabelStyledComponents = styled(IntermediateLabelStyled)`
font-weight: bold;
font-size: 30px;
`;
// DOES NOT WORK
const ExtraStyledLabelComponent = styled(IntermediateLabelComponent)`
font-weight: bold;
font-size: 30px;
`;
// DOES NOT WORK
const ExtraStyledLabelForwardRef = styled(IntermediateLabelForwardRef)`
font-weight: bold;
font-size: 30px;
`;
const Container = () => (
<App>
<GlobalStyle />
<StyledLabel $isSelected>React 18 + styled-components 6. Transient props in intermediate components</StyledLabel>
<StyledLabel $isSelected>Green text is ok, red is not</StyledLabel>
<ExtraStyledLabelStyledComponents $isSelected={true}>With styled component</ExtraStyledLabelStyledComponents>
<ExtraStyledLabelComponent $isSelected={true}>With React component</ExtraStyledLabelComponent>
<ExtraStyledLabelForwardRef $isSelected={true}>With forwardRef</ExtraStyledLabelForwardRef>
<IntermediateLabelComponent $isSelected={true}>Function component directly</IntermediateLabelComponent>
</App>
);
const root = createRoot(document.getElementById("app"));
root.render(<Container />);
这似乎是设计使然。 https://github.com/styled-components/styled-components/issues/4266
我尝试过
shouldForwardProp
但无论如何都无法使其工作。
解决方案是将其重命名为普通道具。
这是不可能的,因为它就是这样设计的。文档 (https://styled-components.com/docs/api#transient-props) 中指出:
如果你想阻止样式组件使用的 props 被传递到底层 React 节点或渲染到 DOM 元素,你可以在 prop 名称前加上美元符号 ($) 前缀,将其变成瞬态 prop。
这意味着 React 节点的行为是正确的,无法访问瞬态 props。您可以使用普通道具并手动过滤它们。