remix-run / remix

Build Better Websites. Create modern, resilient user experiences with web fundamentals.
https://remix.run
MIT License
29.98k stars 2.53k forks source link

Styled Components Injects Class Names in Wrong positions when rendering with SSR / Remix #4907

Closed OmarKhled closed 1 year ago

OmarKhled commented 1 year ago

What version of Remix are you using?

1.5.1

Steps to Reproduce

I'm witnessing a weird behavior when using styled-components with remix / SSR

To Reproduce this issue, navigate to https://ieee-nu-store-dt1asq0sv-omarkhled.vercel.app/ and you will find a ProdcutCard component on the root route, navigate to any other route and return back, and will find that the style of the cart button in the ProductCart Component did change

Expected Behavior

The ProductcCard Component Should be rendered as follows

image

Actual Behavior

The component renders fine on the first render on the root route, but after hitting any other route and returning back to the root route it breaks and shows as follows:

image

The code for the ProductCard Component is as follows

ProductCard.tsx

import Button from "../Button";

function ProductCard({ product }: props) {
  return (
    <>
      <Wrapper>
        ....
        <ButtonsWrapper>
          <Cart
            onClick={addToCart}
            mode={addedToCart ? "secondary" : "primary"}
            disabled={loading}
            key="cart-button"
          >
            {addedToCart ? "Added!" : "Add to cart"}
            {loading && <LoadingSpinner src="/images/responses/loader.svg" />}
          </Cart>
          <ShareButton mode="secondary" aria-label="share">
            <Icon id="share" />
          </ShareButton>
        </ButtonsWrapper>
      </Wrapper>
    </>
  );
}

const Cart = styled(Button)`
  flex: 1.1;
  display: flex;
  justify-content: center;
  gap: 10px;
`;
const ShareButton = styled(Button)`
  padding: 0.9rem;
`;
const Wrapper = styled.div`
  --border-radius: ${clamp(15, 20)};
  --columnGap: ${clamp(20, 30)};
  display: flex;
  flex-direction: column;
  gap: var(--columnGap);
  justify-content: space-between;
  width: 100%;
  height: 100%;
  margin: auto;
  background-color: var(--azure-15);
  padding: 1.9rem 1.5rem;
  border-radius: var(--border-radius);
  box-shadow: var(--box-shadow-lg);
  border: var(--border-lg);
`;
const ButtonsWrapper = styled.div`
  display: flex;
  justify-content: space-between;
  gap: 0.625rem;
`;
export default ProductCard;

Button.tsx

const Button = styled.button<{ mode: "primary" | "secondary" | "dark" }>`
  display: grid;
  /* justify-content: center; */
  align-items: center;
  text-align: center;
  color: var(--mintCream);
  padding: ${clamp(9, 10)} ${clamp(20, 30)}; // this clamp function just generates the css clamp func with calculating the values with some equations
  box-shadow: var(--box-shadow-md);
  border: var(--border-md);
  border-radius: 12px;
  text-decoration: none;
  cursor: pointer;
  transition: all 500ms ease;
  font-size: ${clamp(13, 16)};
  &:disabled {
    cursor: not-allowed;
    opacity: 0.7;
  }
  @media (hover: hover) and (pointer: fine) {
    &:hover:enabled {
      transform: translateY(-2px);    }
  }
  width: fit-content;
`;

This problem only happens in production and works fine on the local server...

On inspecting elements, I find that the class name of the Cart Component is also injected into the ShareButton Element

I don't know whether the cause of this behavior is something in styled-components or the SSR in remix.run but I think this issue is relevant #1032 I get the error Warning: Prop `className` did not match. Server: "sc-dUWWNf kGyxhI" Client: "sc-iqcoie JlZYN" also as the above issue.

Can you guide me through this?

clgeoio commented 1 year ago

Could be related to https://github.com/remix-run/remix/issues/5144

machour commented 1 year ago

Duplicate of #1032