Reputation: 3421
I was following this tutorial on using React.forwardRef
, where make this component:
import React from "react";
const Search = React.forwardRef<HTMLInputElement>((props, ref) => {
return <input ref={ref} type="search" />;
});
export default Search;
However, running my app, the component causes the following error:
Component definition is missing display name react/display-name
Based on this question, I thought I might do something like this:
const Search = MySearch = React.forwardRef<HTMLInputElement>((props, ref) => {
return <input ref={ref} type="search" />;
});
export default Search;
But this did not fix the problem either.
So then, how can I give my component a display name?
Upvotes: 125
Views: 92035
Reputation: 945
Base on A. Backhagen 's answer, add a few edits to work with typescript:
const ComponentName = (props, ref: React.ForwardedRef< HTMLInputElement >) => {
return (
<div ref={ref}></div>
);
};
export const ExportName = forwardRef(ComponentName);
Upvotes: 0
Reputation: 39
Here is my solution the previous ones didnt work for me:
import React, { forwardRef, Ref } from 'react';
import { SliderItemContainer, SliderItemContent } from '../styles/SliderItem.styles';
import { SliderItemType } from '../utils/Slider.data';
type SliderItemProps = {
item: SliderItemType;
};
const SliderItem = ({ item }: SliderItemProps, ref: Ref<HTMLDivElement>) => {
return (
<SliderItemContainer ref={ref} image={item.image}>
<SliderItemContent>
<h1>{item.title}</h1>
<p>{item.description}</p>
<button>{item.buttonText}</button>
</SliderItemContent>
</SliderItemContainer>
);
};
export default forwardRef(SliderItem);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Usage outside of the component is also simple I just wrapped SliderItem component with motion, named it MotionSliderItem.
const MotionSliderItem = motion(SliderItem);
<MotionSliderItem ..... />
Upvotes: 2
Reputation: 4742
You could use a named function (see function Search
) instead of the anonymous arrow fn, like in the example below.
const Search = React.forwardRef<HTMLInputElement>(function Search(props, ref) {
return <input ref={ref} type="search" />;
});
export default Search;
Upvotes: 49
Reputation: 1413
All the answers here using types, here is our solution with interfaces:
import { Ref, forwardRef } from 'react';
interface Props {
"foo": string
}
const Input = ({ foo }: Props, ref: Ref<HTMLInputElement>) => {
return <input foo={foo} ref={ref} type="text" />;
};
export default forwardRef(Input);
Upvotes: 0
Reputation: 803
In addition to Larsson's response (which I think it's the way to go), if you still want to have the typings you can do something like this:
import { forwardRef, ForwardRefRenderFunction } from "react";
type MyComponentProps = {
something: string;
}
type RefProps = {
something: string;
}
const MyComponent: ForwardRefRenderFunction<RefProps, MyComponentProps> = (props, ref) => {
return <div>Works</div>;
}
export default forwardRef(MyComponent);
Upvotes: 20
Reputation: 1407
I've recently had the same issue and resolved it this way. Might not be the prettiest but could be preferred to some. Where ComponentName
is the React name and the ExportName
is what you will import in other places.
const ComponentName = (props, ref) => {
return (
<div ref={ref}></div>
);
};
export const ExportName = forwardRef(ComponentName);
Upvotes: 55
Reputation: 165
I had a similar issue today. I use the DetailsList from @fluentui: Each column has an optional property onRender
which passes the current item so that you can return a custom component to format your data. I was trying something like this: onRender: (item: PlannerTask) => <TitleColumn item={item} />
. This gave me the error. I found two ways to fix it for me.
onRender: function titleColumn (item: PlannerTask) { return <TitleColumn item={item} /> }
In my component file I also export a function that returns the component:
export const createTitleColumn = (item: PlannerTask): JSX.Element => {
return <TitleColumn item={item} />
}
Then I just pass this:
onRender: createTitleColumn
I like this variant most because it doesn't overcomplicate things and I personally found the second option to be very readable as well.
Overall I think that the eslint error was a false positive in my case, because there's nothing wrong with my original code. However I try to avoid disabling linting or compiler errors/rules, because they don't just exist to annoy us ;)
Upvotes: 0
Reputation: 181
import React from "react";
const Search = React.forwardRef<HTMLInputElement>(function Search(props, ref) {
return <input ref={ref} type="search" />;
});
export default Search;
In this way, you can fix the problem. I suggest we'd better know why eslint limit the way of writting
Upvotes: 18
Reputation: 11977
The Component definition is missing display name react/display-name
message is likely coming from a tool like eslint.
It is a linting rule that exists in order to help you follow style guides and/or conventions regarding what is considered good practice when writing React code.
That particular rule in eslint is explained in further details here: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/display-name.md
From that page you can also find why it exists and what the displayName
property on React Components is good for, namely to help when debugging, since it means that it will print your component's displayName
property to the console instead of just input
.
Also, from that link, you can find that when you are using function components, you can address that by setting the displayName
property on the component. This should probably help you:
import React from "react";
const Search = React.forwardRef<HTMLInputElement>((props, ref) => {
return <input ref={ref} type="search" />;
});
Search.displayName = "Search";
export default Search;
Another option is to just disable that particular linter, using a comment with // eslint-disable-next-line react/display-name
or similar just above the declaration of your component.
That would however mean that if you were to need to debug your app, this component would simply be called input
instead of Search
, which might make the debugging a bit harder.
Upvotes: 256
Reputation: 1424
Put this at the beginning of your file:
/* eslint-disable react/display-name */
You could also try this:
// eslint-disable-next-line react/display-name
Upvotes: -1