Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Styling react-router-dom Link using styled-components getting warning when passing props

import styled from 'styled-components';
import {Link} from 'react-router-dom';

const LS = {};

LS.NavFixedItem_LINK = styled(Link)`

  display: flex;
  justify-content: ${props => props.tempLeftProp ? 'flex-start' : 'center'};
  align-items: center;
`;

function NavFixedItem(props) {
  return(
    <LS.NavFixedItem_LINK to={props.link} tempLeftProp={props.toLeft}>
      {props.name}
    </LS.NavFixedItem_LINK>
  );
}

I'm getting the error:

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

I pass props to my styled-components all the time. I don't know if the problem is that I'm styling a component Link instead of a regular HTML element.

QUESTION

Why am I getting this error? Is it safe to just ignore it?

PS: The styles are being applied as intended.

like image 255
cbdeveloper Avatar asked Sep 25 '19 08:09

cbdeveloper


3 Answers

Use transient props

With the release 5.1.0 you can use transient props. This way you do not need an extra wrapper i.e. unnecessary code is reduced:

Transient props are a new pattern to pass props that are explicitly consumed only by styled components and are not meant to be passed down to deeper component layers. Here's how you use them:

const Comp = styled.div`
  color: ${props => props.$fg || 'black'};
`;

render(<Comp $fg="red">I'm red!</Comp>);

Note the dollar sign ($) prefix on the prop; this marks it as transient and styled-components knows not to add it to the rendered DOM element or pass it further down the component hierarchy.

The new answer should be:

styled component:

LS.NavFixedItem_LINK = styled(Link)`
  display: flex;
  justify-content: ${props => props.$tempLeftProp ? 'flex-start' : 'center'}; // '$' added
  align-items: center;
`;

parent component:

function NavFixedItem(props) {
  return(
    <LS.NavFixedItem_LINK 
      to={props.link} 
      $tempLeftProp={props.toLeft} // '$' signals the transient prop
    >
      {props.name}
    </LS.NavFixedItem_LINK>
  );
}
like image 148
EliteRaceElephant Avatar answered Oct 10 '22 07:10

EliteRaceElephant


Internally, React Router's Link passes all the its props to an <a> DOM element. Except the ones used by Link, like to. So the styles work because the props are interpreted by Styled Components, but then the same prop is passed again to the inner <a>, which triggers the (harmless) error message.

You could try having a wrapper with nested styles, like this:

LS.NavFixedItem_LINK = styled.div`
  a {
    display: flex;
    justify-content: ${props => props.tempLeftProp ? 'flex-start' : 'center'};
    align-items: center;
  }
`;

function NavFixedItem(props) {
  return(
    <LS.NavFixedItem_LINK tempLeftProp={props.toLeft}>
      <Link to={props.link}>
        {props.name}
      </Link>
    </LS.NavFixedItem_LINK>
  );
}
like image 20
Raicuparta Avatar answered Oct 10 '22 08:10

Raicuparta


another thing you could try the "to" prop on a react Link tag can take two different values a string or an object.

  1. If it's a string, it represents the absolute path to link to, e.g. /users/123 (relative paths are not supported).
  2. If it's an object, it can have four keys:

    • pathname: A string representing the path to link to.
    • query: An object of key:value pairs to be stringified.
    • hash: A hash to put in the URL, e.g. #a-hash.
    • state: State to persist to the location.

your above code can be represented as:

import styled from 'styled-components';
import {Link} from 'react-router-dom';

const LS = {};

LS.NavFixedItem_LINK = styled(Link)`

  display: flex;
  justify-content: ${props => props.to.state.tempLeftProp ? 'flex-start' : 'center'};
  align-items: center;
`;

function NavFixedItem(props) {
  return(
    <LS.NavFixedItem_LINK to={{ pathname: props.link, state: {tempLeftProp: props.toLeft} }}>
      {props.name}
    </LS.NavFixedItem_LINK>
  );
}
like image 3
murrow Avatar answered Oct 10 '22 06:10

murrow