Search code examples
reactjstypescriptstyled-componentsreact-typescriptreact-flow

Styled Components not being recognized in React


I have the following Styled component (not posting complete, doesn't make any difference): It extends Handle (and HandleProps) from 'reactflow' library

interface CustomHandleProps extends HandleProps {
  istarget?: boolean;
  zoomedout?: boolean;
  placement: number;
  placementOffset: string;
  nodeSize: string;
  titleMaxLength?: 1 | 2;
  showTitle?: string;
  customTitle?: PointTitleCustomization;
  format?: PointFormat;
}

export const CustomHandle = styled(Handle).attrs(({ type }) => ({ type }))<CustomHandleProps>`
  width: ${({ nodeSize }) => nodeSize};
  height: ${({ nodeSize }) => nodeSize};
  border-radius: ${({ format }) => (format ? (format === 'circle' ? '50%' : '0') : '50%')};
  display: flex;
  border: ${({ zoomedout }) => (!zoomedout ? ' 1px solid #fff' : 'none')};
...
`

And it's being used like:

import * as Styled from './diagram-card-edge.styles';
<Styled.CustomHandle
  key={`${edgePosition}-${type}-${index}-${nodeData.id}`}
  id={`${edgePosition}-${type}-${index}-${nodeData.id}`}
  position={position}
  istarget={isTarget}
  type={type}
  zoomedout={zoomedOut}
  isConnectable={!zoomedOut}
  placement={calcEdgePlacement(
    index,
    nodeData.edges[edgePosition]?.nodes as number,
    nodeData.edges[edgePosition]?.alignOffset,
    nodeData.edges[edgePosition]?.align
  )}
  isConnectableStart={!nodeData.lockDiagram}
  placementOffset="-0.3rem"
  nodeSize="0.5rem"
/>;

But React doesn't seem to recognize it as a Styled component, getting errors like:

Warning: React does not recognize the nodeSize prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase nodesize instead. If you accidentally passed it from a parent component, remove it from the DOM element. or Warning: React does not recognize the placementOffset prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase placementoffset instead. If you accidentally passed it from a parent component, remove it from the DOM element.

or

Warning: Received false for a non-boolean attribute zoomedout.

If you want to write it to the DOM, pass a string instead: zoomedout="false" or zoomedout={value.toString()}.

If you used to conditionally omit it with zoomedout={condition && value}, pass zoomedout={condition ? value : undefined} instead.

The values of the attrs are being passed correctly in the component, I checked the logs for it. I tried to do some modifications like the ones in styled-component .attrs - React does not recognize prop , but none seemed to work.

React version: 17.0.2 Styled-Components version: 5.3.5


Solution

  • So, there was 2 problems here: First and foremost, it was missing the main import of reactflow styles, which was breaking a lot of stuff in the code

    import 'reactflow/dist/style.css';
    

    Second, when needed to pass more props and for them to be recognized, you need to use withConfig and shouldForwardProp so the example in the question has become:

    export const CustomHandle = styled(Handle).withConfig({
        shouldForwardProp: (prop) =>
            !['istarget', 'zoomedout', 'cardEdgeHandlePositionOffset', 'cardEdgeHandleDimensions'].includes(prop)
    })<CustomHandleProps>`
    ...
    

    and this is how I managed to fix the warnings of props and the styling of the custom reactflow component.