Skip to content

Instantly share code, notes, and snippets.

@jimfb
Last active February 10, 2023 15:08
Show Gist options
  • Save jimfb/d99e0678e9da715ccf6454961ef04d1b to your computer and use it in GitHub Desktop.
Save jimfb/d99e0678e9da715ccf6454961ef04d1b to your computer and use it in GitHub Desktop.

The unknown-prop warning will fire if you attempt to render a DOM element with a prop that is not recognized by React as a legal DOM attribute/property. You should ensure that your DOM elements do not have spurious props floating around.

There are a couple of likely reasons this warning could be appearing:

  1. Are you using {...this.props} or cloneElement(element, this.props)? Your component is transferring its own props directly to a child element (eg. https://facebook.github.io/react/docs/transferring-props.html). When transferring props to a child component, you should ensure that you are not accidentally forwarding props that were intended to be interpreted by the parent component.

  2. You are using a non-standard DOM attribute on a native DOM node, perhaps to represent custom data. If you are trying to attach custom data to a standard DOM element, consider using a custom data attribute (https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes).

  3. React does not yet recognize the attribute you specified. This will likely be fixed in a future version of React. However, React currently strips all unknown attributes, so specifying them in your React app will not cause them to be rendered.


To fix this, composite components should "consume" any prop that is intended for the composite component and not intended for the child component. Example:

Bad: Unexpected layout prop is forwarded to the div tag.

function MyDiv(props) {
  if (props.layout === 'horizontal') {
    // BAD! Because you know for sure "layout" is not a prop that <div> understands.
    return <div {...props} style={getHorizontalStyle()} />
  } else {
    // BAD! Because you know for sure "layout" is not a prop that <div> understands.
    return <div {...props} style={getVerticalStyle()} />
  }
}

Good: The spread operator can be used to pull variables off props, and put the remaining props into a variable.

function MyDiv(props) {
  const { layout, ...rest } = props
  if (layout === 'horizontal') {
    return <div {...rest} style={getHorizontalStyle()} />
  } else {
    return <div {...rest} style={getVerticalStyle()} />
  }
}

Good: You can also assign the props to a new object and delete the keys that you're using from the new object. Be sure not to delete the props from the original this.props object, since that object should be considered immutable.

function MyDiv(props) {

  const divProps = Object.assign({}, props);
  delete divProps.layout;
  
  if (props.layout === 'horizontal') {
    return <div {...divProps} style={getHorizontalStyle()} />
  } else {
    return <div {...divProps} style={getVerticalStyle()} />
  }
}
@dan-mckay
Copy link

@jimfb Is it safe to say that all unknown props that are currently firing warnings were previously being stripped away as unrecognised?

@gaearon
Copy link

gaearon commented Jul 5, 2016

@zediah

it'll strip refs and any other fields that might be introduced/I might not be aware of.

You can pass both key and ref that you read directly from the element, as part of the argument you to React.createElement. This won’t work for string refs (because they require owner which wouldn’t get copied), but it will work for callback refs (ref={inst => ...}).

However this sounds like an anti-pattern. If you’re trying to remove a prop post factum, it probably means it shouldn’t have been there in the first place.

Instead, you can change your API to be like this:

<Animation>
  <AnimationChild someArg={42}>
    <div />
  </AnimationChild>,
  <AnimationChild someArg={100}>
    <Whatever />
  </AnimationChild>
</Animation>

@gaearon
Copy link

gaearon commented Jul 5, 2016

@dmcaodha

Is it safe to say that all unknown props that are currently firing warnings were previously being stripped away as unrecognised?

Yes.

@zediah
Copy link

zediah commented Jul 6, 2016

@gaearon

Greatly appreciate the reply and the suggestion. You're probably right in that I've been using an anti-pattern, I figured my way looked 'neater' and I never thought of all the props having to be known by the child, rather that the child just cherry-picked the props given to it.

I think my example shows a separate problem where it's not possible to truly remove a prop when cloning an element. You can make it undefined, which is very similar - but this still throws the warning. Is it really still something to warn about if the value is undefined? (it could have a default value set, but then it wouldn't be undefined)

@tyv
Copy link

tyv commented Jul 7, 2016

Hope this will be helpful, spent some time migrating on 15 too
https://www.npmjs.com/package/pick-react-known-prop

@oztune
Copy link

oztune commented Jul 15, 2016

@gaearon

However this sounds like an anti-pattern. If you’re trying to remove a prop post factum, it probably means it shouldn’t have been there in the first place.

I think there are cases where it's not an anti-pattern. For example a library may choose to 'extend' the API of a native element with some custom attributes. So the user may create and element with invalid props which the library then strips out before sending the element down to react.

I understand some purists may not appreciate such a library, but I think there are cases where it's useful and React should try to cater to that.

@fetis
Copy link

fetis commented Jul 27, 2016

I just want to make a note, that syntax

const { layout, ...rest } = props

is not a part of ES6, but currently only Stage 2 proposal of ES7.

So, for real life usage there's only delete variant or you can use Lodash .omit(), .pick() functions.

@faceyspacey
Copy link

@zediah did you ever come up with a solution? Creating an element definitely isn't it, and it can be nice to not have to add additional components to the tree.

@prasanna1211
Copy link

Hy, is there a way where I can specifically cut down props which are not required for my html element? For example I have a parent Component which wraps which wraps standard HTML input component . When I pass props from wrapper I want to remove props in CustomInput which are not standard html props for input. Apart from checking every valid props is there any other way ?

@moparlakci
Copy link

extract your own props from it

const { isMenuOpen, ...props } = this.props

then pass props to your component (without this)

<Header {...props} />

@skavan
Copy link

skavan commented Mar 30, 2021

Are they any different ways to handle this problem in 2021? In my case, the props sent to a child component are dynamic and unknown at runtime. So I need a way of (a) stripping them out automagically or (b) suppressing the warning.
(a) would be better! Ideas?

@numpde
Copy link

numpde commented Feb 10, 2023

What's the "source of truth" for the known props?

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