direflow
direflow copied to clipboard
Styled Components plugin makes components crash when a property is changed
Describe the bug
Components that use the Styled Components plugin crash when a property is changed. This only happens in production mode (direflow-scripts build
). In development mode, when you change a property, the style tag is appended at a different position that it is on the initial render and the styles are not applied to the component anymore. The generated class names don't exist in the component's DOM, but also the CSS properties are not updated accordingly.
To reproduce
Steps to reproduce the behavior:
The behavior can be reproduced in this Direflow project: https://sample-direflow-project.vercel.app/
- Inspect the page and select
<styled-component>
- Change its
bgColor
property tored
:$0.bgColor = 'red'
- See error
Project's repo: https://github.com/kcmr/sample-direflow-project
Expected behavior
When you change a property, the updated styles are applied and the component doesn't crash.
Package Manager:
npm
Screenshots
Production mode
Development mode on initial render
Development mode after changing a prop
I'm also coming up against this issue. Is there any progress on this or any idea why this is happening? Any workarounds?
Found a workaround by wrapping web-components in a HOC. The weird thing is that the web-component will only accept props if they are defined on .defaultProps
of web-component.
const withStyledComponents = function (Component: any) {
const StyleSheetedComponent = ({ children, insertionPoint }: any) => {
return (
/* @ts-ignore */
<StyleSheetManager target={insertionPoint}>{children}</StyleSheetManager>
);
};
return function (props: any) {
const [mounted, setMounted] = useState(false);
const insertionPoint = useRef(null);
useEffect(() => {
setMounted(true);
}, []);
const strippedProps: any = {};
Object.entries(props).forEach(([key, value]) => {
if (`${props[key]}` !== "undefined") {
strippedProps[key] = value;
}
});
return (
<>
<span ref={insertionPoint} id="styled-components-ref"></span>
{insertionPoint.current && (
<StyleSheetedComponent insertionPoint={insertionPoint.current}>
<Component {...strippedProps} />
</StyleSheetedComponent>
)}
</>
);
};
};
Hi @brentonr94, the trick is to wrap the component you created before assigning the defaultProps. e.g.
const Button = withStyledComponents((props) => {
const { onClick } = props;
return (
<StyledButton onClick={onClick}>
<slot key="children" name="children" />
</StyledButton>
);
});
Button.defaultProps = { onClick: null };
export default Button;
Great thank you! I was just reworking my comment as I found defining the props in the direflow config also resolved my issue of props not being passed through. Thanks again!