@types/styled-components
package and had problems.Definitions by:
in index.d.ts
) so they can respond.Here is a simple repro. I can use forwarded ref on regular input, but not with styled one, it gives weird Typescript error, I am not sure what it means really.
https://codesandbox.io/s/o5ompq26j6
import * as React from 'react'
import styled from 'styled-components'
const StyledInput = styled.input`
background-color: yellow;
`
export const WithInput = React.forwardRef<HTMLInputElement>((props, ref) => (
<React.Fragment>
<input ref={ref} />
<StyledInput ref={ref} />
</React.Fragment>
))
Type 'string | ((instance: HTMLInputElement | null) => any) | RefObject<HTMLInputElement> | undefined' is not assignable to type 'string | (string & ((instance: HTMLInputElement | null) => any)) | (string & RefObject<HTMLInputElement>) | (((instance: Component<ThemedOuterStyledProps<ClassAttributes<HTMLInputElement> & InputHTMLAttributes<HTMLInputElement> & { ...; }, any>, any, any> | null) => any) & string) | ... 5 more ... | undefined'.
Type '(instance: HTMLInputElement | null) => any' is not assignable to type 'string | (string & ((instance: HTMLInputElement | null) => any)) | (string & RefObject<HTMLInputElement>) | (((instance: Component<ThemedOuterStyledProps<ClassAttributes<HTMLInputElement> & InputHTMLAttributes<HTMLInputElement> & { ...; }, any>, any, any> | null) => any) & string) | ... 5 more ... | undefined'.
Type '(instance: HTMLInputElement | null) => any' is not assignable to type 'RefObject<Component<ThemedOuterStyledProps<ClassAttributes<HTMLInputElement> & InputHTMLAttributes<HTMLInputElement> & { invalid?: boolean | undefined; }, any>, any, any>> & RefObject<...>'.
Type '(instance: HTMLInputElement | null) => any' is not assignable to type 'RefObject<Component<ThemedOuterStyledProps<ClassAttributes<HTMLInputElement> & InputHTMLAttributes<HTMLInputElement> & { invalid?: boolean | undefined; }, any>, any, any>>'.
Property 'current' is missing in type '(instance: HTMLInputElement | null) => any'.
Really Really need this fixed to swap to 4.0.0 +1
@johnnyreilly Do you think you would able to help with this? Seems that original authors lost interest. There is a bunch of other issues related to styled-components and nobody paying attention to those. Or please ping someone who could help.
Feel free to submit at PR - this can be reviewed and merged to unblock you.
@johnnyreilly Sorry, but that's just the thing, I don't understand what's the issue. I would be happy to do a PR if I would only half understand why it's happening :(
I'll look into this today.
Any word on this? It's also blocking our upgrade of styled-components
.
At the moment I didn't come up with a solution yet. It looked harder than I expected. The issue is that what we called StyledComponentClass
is not a class component anymore it is a forwarding component that needs to carry information of what it was created for to correctly accept refs.
A reduced repro:
const StyledInput = styled.input` `;
const inputRef = React.createRef<HTMLInputElement>();
<StyledInput ref={inputRef} />; // error
Change would require adding new generic parameters and might be breaking.
I'll keep you updated.
Also blocking our upgrade of styled-components to v4 for a week now :<
Hi! Do I understand correctly that these problems are due to the fact that the authors of styled-components
have mixed up the Component
and ComponentClass
classes?
For me, it's expecting either string & ((r: HTMLDivElement) => any
or string & React.RefObject<HTMLDivElement>
and the like. Every type passed requires it to be string &
which doesn't look right. I should be able to just pass a RefObject
or function.
My current workaround is to add as any
.
ref={this.captureFn as any}
This seems to be a consequence of Ref
should just make a PR to rip the band-aid off and drop string from it,
it'll never work on anything but class components rendering class/host
components and is deprecated anyway.
Closing as with @types/styled-components: 4.1.7
this seems to be working correctly now. Thank you @Jessidhia for amazing work!
Closing as with
@types/styled-components: 4.1.7
this seems to be working correctly now. Thank you @Jessidhia for amazing work!
Unfortunately for me this is not working yet. I'm still using the @cmrigney solution
Still borked for me as well.
"@types/styled-components": "^4.1.12",
"ts-lint": "^4.5.1",
"typescript": "^3.3.3333"
"styled-components": "^4.1.3"
Make sure you really have a some latest version of @types/react
package as well. Especially with Yarn, I've got burned many times where there were different versions of that package was spread across causing havoc. The best cure AFAIK is to manually edit yarn.lock
and remove all instances of @types/react
and then reinstall.
"@types/react": "^16.8.7",
// node_modules/@types/react/package.json
"version": "16.8.7",
Problem still persists :(
@superhawk610 is there a node_modules/@types/styled-components/node_modules/@types/react/package.json
?
Yeah, nice catch. It's on 16.8.6
. However, removing that directory and replacing it with the updated types I previously mentioned doesn't fix the error.
@superhawk610 replacing single folder won't catch them all as there might be other diverged react types.
The problem stems from some type packages targeting dependencies with wildcard *
version. This is quite common for React based libraries. For example @types/styled-components
specifies @types/react
as a dependency with version *
. Package managers treat it as any version goes, so if you update @types/react
, versions will diverge and @types/styled-components
will stay on the older version @types/react
, usually when it was first written to lockfile.
Do you use Yarn? You can search for @types/react@*
in yarn.lock
. This should be something like:
"@types/react@*", "@types/react@^16.8.7":
version "16.8.7"
...
If you have another @types/react
statement before or after this one, then you have multiple React types in repository.
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/33015 - looks like it should be a peerdependency instead.
@superhawk610 I've found using the resolutions
property in the package.json
file very helpful for solving package version mismatches, specifically for @types/react
.
I haven't had a chance to properly look into your issue, but if it is indeed a an issue of conflicting definitions, try adding the following to your package.json
file.
"resolutions": {
"@types/react": "16.8.7"
}
Thanks for the tips, everybody. I have a working solution, but it's still not pretty.
const ref = React.useRef() as React.MutableRefObject<HTMLImageElement>;
// ...
return <Image ref={ref} style={style} src={cat} />;
It seems that React.useRef<T>()
returns a React.MutableRefObject<T | undefined>
but SC's ref
only accepts React.MutableRefObject<T>
, not React.MutableRefObject<T | undefined>
. The type assertion has it passing for now, and it appears this is off-topic from the original issue so I may open a new issue if I can get a minimal reproducible repo put together.
I ran into this today, I'm just not using ref
for now.
e.g.
export const Component: React.Fn<React.HTML<"tr">> = ({
children,
ref,
...props
}) => <Wide {...props}>{children}</Wide>;
const Wide = styled.div`
padding: 1em 0;
text-align: center;
`;
For me the issue was simply using the wrong type on useRef. On an <a>
element is used useRef<HTMLLinkElement>(null)
instead of useRef<HTMLAnchorElement>(null)
.
This issue persists, unfortunately. The fix I found works but is verbose. I'm using React.forwardRef
.
React.forwardRef((
{...props},
ref: ((instance: HTMLInputElement | null) => void) | React.MutableRefObject<HTMLInputElement | null> | null
) => {
return <StyledInput ref={ref} />
})
This worked for me:
`
import React from 'react';
import styled from 'styled-components';
const ForwardRefComponent = React.forwardRef((props, ref) => );
const StyledComponent = styled(ForwardRefComponent)'
grid-column-start: 1;
grid-column-end: span 6;
position: relative;
height: 100%;
width: 100%;
';
export default StyledComponent;
`
My current workaround is to add
as any
.ref={this.captureFn as any}
i wish this simple solution worked for me, but for some reason it does not.
using "react": "^16.13.0", "styled-components": "^5.0.0", "styled-components": "^5.0.0",
any ideas?
I see the issue is closed but even with very up to date version of the libraries the error persists for me.
I found a work around here, hope this help
const StyledInput = styled.input``
export const Input = forwardRef<HTMLInputElement, Omit<JSX.IntrinsicElements['input'], 'ref'>>(
({ ...props }, forwardedRef) => {
console.log('forwardedRef', forwardedRef) // inputRef
return <StyledInput ref={forwardedRef} {...props} />
})
Most helpful comment
At the moment I didn't come up with a solution yet. It looked harder than I expected. The issue is that what we called
StyledComponentClass
is not a class component anymore it is a forwarding component that needs to carry information of what it was created for to correctly accept refs.A reduced repro:
Change would require adding new generic parameters and might be breaking.
I'll keep you updated.