3
votes

With styled components, I can pass in values and then get conditional css based on those values. For instance, I can do,

const ContainerStyled = styled.div<{isOpen: boolean}>`
  ${({ isOpen }) => isOpen
    ? background-color: red
    : ''
  }
`

However, I'm wondering if it's possible to conditionally render a different component, based on that value? For instance, something like,

const ContainerStyled = styled(isOpen ? ArrowUpIcon : ArrowDownIcon)`
  ${({ isOpen }) => isOpen
    ? background-color: red
    : ''
  }
`
2
On which scope is isOpen? On writing styled(isOpen ? ArrowUpIcon : ArrowDownIcon) does isOpen already evaluated? Your example not clear. Please try showing expected usecase of renderingDennis Vash
Also, it seems like an XY problem: xyproblem.info, please explain what the actual issue and not how you trying to solve itDennis Vash

2 Answers

2
votes

I'm guessing that you asking if you can change the styled target depending on condition.

For that you need to make simple steps:

  1. The custom component has to pass the className prop.
  2. Use as API with condition.

In the next example, the button toggles between rendering a styled.div and styled(Component).

const Container = styled.div`
  width: 100px;
  height: 100px;
  background-color: ${({ isOpen }) => (isOpen ? `red` : `blue`)};
`;

const Component = ({ className }) => <div className={className}>Hello</div>;

const App = () => {
  const [isOpen, toggle] = useReducer(p => !p, false);
  return (
    <>
      <Container as={isOpen ? Component : 'div'} isOpen={isOpen} />
      <button onClick={toggle}>Toggle</button>
    </>
  );
};

Edit misty-meadow-j27j7

1
votes

You can attach as polymorphic prop using attrs chainable method based on passed isOpen prop:

const ContainerStyled = styled(ArrowDownIcon).attrs(({ isOpen }) => ({
  as: isOpen ? ArrowUpIcon : undefined
}))`
  background-color: ${({ isOpen }) => isOpen ? 'red' : ''};
`;