38

I'm trying to create a wrapper component around the react-router-dom NavLink component.

I would like my custom component to accept all of NavLinks props, and proxy them down to NavLink.

However when I do this, I'm getting:

Warning: React does not recognize the staticContext prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase staticcontext instead. If you accidentally passed it from a parent component, remove it from the DOM element.

A working demo of the issue can be found here:

Richard-Degenne
  • 2,649
  • 2
  • 21
  • 41
Nicolas Widart
  • 857
  • 2
  • 10
  • 27

5 Answers5

78

There is a way to overcome that is using:

const { to, staticContext, ...rest } = this.props;

So your ...rest will never contain staticContext

Khoa
  • 2,047
  • 14
  • 12
13

This is a common problem with a simple solution as documented in the React documentation:

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.

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()} />
  }
}

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()} />
  }
}
Nathaniel Hill
  • 223
  • 1
  • 7
3

The given answer by the React docs was not quite good enough for my situation, so I found/developed one which isn't perfect, but is at least not so much of a hassle.

You can see the Q/A in which it arose here: What is Reacts function for checking if a property applies?

The gist is, use a function to pick the bad props out for you.

const SPECIAL_PROPS = [
    "key",
    "children",
    "dangerouslySetInnerHTML",
];

const defaultTester = document.createElement("div")
function filterBadProps(props: any, tester: HTMLElement = defaultTester) {
    if(process.env.NODE_ENV !== 'development') { return props; }

    // filter out any keys which don't exist in reacts special props, or the tester.
    const out: any = {};
    Object.keys(props).filter((propName) => 
        (propName in tester) || (propName.toLowerCase() in tester) || SPECIAL_PROPS.includes(propName)
    ).forEach((key) => out[key] = props[key]);

    return out;
}

Personally, I felt that the warning was completely useless in the first place, so I added a line which skips the check entirely when not in development mode (and warnings are suppressed). If you feel that the warnings have merit, just remove the line:

if(process.env.NODE_ENV !== 'development') { return props; }

You can use it like this:

public render() {
    const tooManyProps = this.props;
    const justTheRightPropsForDiv = filterBadProps(tooManyProps);
    const justTheRightPropsForSpan = filterBadProps(tooManyProps, document.createElement("span"));

    return (<div {...justTheRightPropsForDiv}>
        <span {...justTheRightPropsForSpan} />
    </div>)
}
Seph Reed
  • 4,704
  • 7
  • 30
  • 65
1

This happens because you probably used {...props} somewhere in your component.

Example from React:

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

We grab layout separately so that it won't be contained in {...rest}.

Hasan Sefa Ozalp
  • 2,344
  • 20
  • 27
0

If someone has this issue with react-admin, check if you don't have a Link as a child of Admin. Like this:

<Admin layout={props => <Layout/>}>
  <Link to="/something">something</Link> <-- causing issue
</Admin>

Just move it to another component. For instance, inside the Layout.

Artur Carvalho
  • 6,046
  • 10
  • 62
  • 91