I am storing a ref in my redux store and using mapStateToProps to expose the ref for components that need access to it.
The ref that is stored looks like:
ref={node => this.myRefToBePutInReduxGlobalStore = node}
What is the correct propType for this ref?
You can create a ref by calling React. createRef() and attaching a React element to it using the ref attribute on the element. We can “refer” to the node of the ref created in the render method with access to the current attribute of the ref.
Refs are a function provided by React to access the DOM element and the React element that you might have created on your own. They are used in cases where we want to change the value of a child component, without making use of props and all.
Refs is the shorthand used for references in React. It is similar to keys in React. It is an attribute which makes it possible to store a reference to particular DOM nodes or React elements. It provides a way to access React DOM nodes or React elements and how to interact with it.
PropTypes is React's internal mechanism for adding type checking to components. React components use a special property named propTypes to set up type checking. When props are passed to a React component, they are checked against the type definitions configured in the propTypes property.
If you want to prop type a ref that only expects native DOM elements, such as a div
or an input
, the correct definition is the following:
refProp: PropTypes.oneOfType([
// Either a function
PropTypes.func,
// Or the instance of a DOM native element (see the note about SSR)
PropTypes.shape({ current: PropTypes.instanceOf(Element) })
])
In the OP question's example, it is not the ref prop type that needs to be declared, but the stuff pointed by the ref, and that will be passed from redux using mapStateToProps
. Prop type for a DOM element would be: myRefToBePutInReduxGlobalStore: PropTypes.instanceOf(Element)
(if it's a DOM element). Although, I would:
myElementToBePutInReduxGlobalStore
(an element is not a ref)Q: What is the correct proptype for a ref in React?
Example use case:
function FancyInput({ inputRef }) {
return (
<div className="fancy">
Fancy input
<input ref={inputRef} />
</div>
)
}
FancyInput.propTypes = {
inputRef: ??? // What is the correct prop type here?
}
function App(props) {
const inputRef = React.useRef()
useLayoutEffect(function focusWhenStuffChange() {
inputRef.current?.focus()
}, [props.stuff])
return <FancyInput inputRef={inputRef} />
}
Today, two kind of refs exist in react:
{ current: [something] }
, usually created by
React.createRef()
helper or React.useRef()
hook[something]
as its argument (like the one in OP example)Note: historically, you could also use a string ref, but it's considered legacy and will be removed from react
The second item is quite simple and requires the following prop type: PropTypes.func
.
The first option is less obvious because you might want to specify the type of element pointed by the ref.
ref
can point to something else than DOM element.
If you want to be totally flexible:
refProp: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({ current: PropTypes.any })
])
The above just enforces the shape of object ref w/ current
property. It will work at all time for any kind of ref. For the purpose of using prop type, which is a way to spot any inconsistencies when you develop, this is probably enough. It seems very unlikely that an object with shape { current: [any] }
, and is passed to a refToForward
prop, would not be an actual ref.
However, you might want to declare that your component does not expect any kind of ref, but only a certain type, given what it needs that ref for.
I have setup a sandbox showcasing a few different way to declare a ref, even some non conventional, and then testing them with many prop types. You can find it here.
If you only expect a ref pointing to a native input element, not any HTML Element
:
refProp: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({ current: PropTypes.instanceOf(HTMLInputElement) })
])
If you only expect a ref pointing to a React class component:
refProp: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({ current: PropTypes.instanceOf(Component) })
])
If you only expect a ref pointing to a functional component using useImperativeHandle
to expose some public method:
refProp: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({ current: PropTypes.object })
])
Note: the above prop type is interesting because it also covers react components and native DOM elements, because they all are inheriting the base javascript Object
There is no single good way to declare the prop type for a ref, it depends of the usage. If your ref points to something very identified, it can be worth adding a specific prop type. Otherwise, just checking the general shape seems enough.
If your code has to run on the server, unless you already polyfill DOM environment, Element
or any other client-side type will be undefined
in NodeJS. You can use the following shim to support it:
Element = typeof Element === 'undefined' ? function(){} : Element
The following React Docs pages gives more insight on how to use refs, both object and callbacks, and also how to use useRef
hook
Answer updated thank to @Rahul Sagore, @Ferenk Kamra, @svnm, and @Kamuela Franco
Very similar to @Pandaiolo's post,
PropTypes.elementType
has now been added
forwardedRef: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({ current: PropTypes.instanceOf(Element) })
]),
PropTypes.instanceOf(Element)
looks to be the correct way to do this now as mentioned by Ferenc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With