Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React 19 styled() override ref of host #3204

Closed
oliviertassinari opened this issue Jul 2, 2024 · 2 comments · Fixed by #3208
Closed

React 19 styled() override ref of host #3204

oliviertassinari opened this issue Jul 2, 2024 · 2 comments · Fixed by #3208

Comments

@oliviertassinari
Copy link

oliviertassinari commented Jul 2, 2024

To reproduce:

import * as React from "react";
import * as ReactDOM from "react-dom/client";
import styled from "@emotion/styled";

function Button(props) {
  const buttonRef = React.useRef();

  React.useEffect(() => {
    buttonRef.current.focus();
  }, []);

  console.log("React", props.ref);

  return (
    <button ref={buttonRef} {...props}>
      Hello
    </button>
  );
}

const SyledButton = styled(Button)({
  color: "red",
});

const App = () => {
  return <SyledButton>Hello</SyledButton>;
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Current behavior:

React 19.0.0-rc.0 fail: https://codesandbox.io/p/sandbox/blissful-danilo-3z4rs3?file=%2Fsrc%2Findex.js%3A1%2C1-35%2C1

SCR-20240703-bwmt

Expected behavior:

React 18.3.1 success: https://codesandbox.io/p/sandbox/peaceful-jones-fqj8kw?file=%2Fpackage.json%3A5%2C12&workspaceId=836800c1-9711-491c-a89b-3ac24cbd8cd8

SCR-20240703-bwqv

Environment information:

  • react version: 19.0.0-rc.0
  • @emotion/react version: 11.11.5

Context

I have noticed this from mui/material-ui#41388. React 19 handles ref as prop by default https://react.dev/blog/2024/04/25/react-19#ref-as-a-prop. So when emotion does

newProps.ref = ref
it overrides the ref used by the component.

The right solution seems to do:

+     // The ref is coming from a React.forwardRef. It might not exist. Since React 19 handles ref as prop, only define it if there is a value.
+     if (ref) {
        newProps.ref = ref;
+     }

since emotion is only trying to be transparent from a ref perspective, with it's styled() wrapper.

return forwardRef((props /*: Props */, ref /*: Ref */) => {

@Andarist
Copy link
Member

Andarist commented Jul 3, 2024

Could you make those codesandboxes public?

@oliviertassinari
Copy link
Author

Ah god, I should default to StackBlitz. Fixed. CodeSandbox fixed a bit it's UX recently by showing the sandbox visibility setting with an icon, but I keep forgetting about it (so are people on Material UI). There should be a setting to configure a default mode in CodeSandbox.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants