web-dev-qa-db-fra.com

Comment étendre un composant stylé sans passer d'accessoires à l'élément DOM sous-jacent?

J'ai un composant stylé qui étend un composant tiers:

import Resizable from 're-resizable';
...
const ResizableSC = styled(Resizable)``;
export const StyledPaneContainer = ResizableSC.extend`
    flex: 0 0 ${(props) => props.someProp}px;
`;


const PaneContainer = ({ children, someProp }) => (
    <StyledPaneContainer
        someProp={someProp}
    >
        {children}
    </StyledPaneContainer>
);

export default PaneContainer;

Cela a entraîné l'erreur suivante dans la console du navigateur:

Avertissement: React ne reconnaît pas l'accessoire someProp sur un élément DOM. Si vous voulez qu'il apparaisse intentionnellement dans le DOM en tant qu'attribut personnalisé, épelez-le en minuscule someProp à la place. Si vous l'avez accidentellement transmis depuis un composant parent, supprimez-le de l'élément DOM

J'ai donc changé l'hélice pour avoir un data-* Nom d'attribut:

import Resizable from 're-resizable';
...
const ResizableSC = styled(Resizable)``;
export const StyledPaneContainer = ResizableSC.extend`
    flex: 0 0 ${(props) => props['data-s']}px;
`;


const PaneContainer = ({ children, someProp }) => (
    <StyledPaneContainer
        data-s={someProp}
    >
        {children}
    </StyledPaneContainer>
);

export default PaneContainer;

Cela fonctionne, mais je me demandais s'il y avait une façon native d'utiliser les accessoires dans le composant stylé sans qu'ils soient transmis à l'élément DOM (?)

19
JoeTidee

Comme suggéré par vdanchenkov on ce problème de github avec les composants de style vous pouvez détruire les accessoires et ne transmettre que ceux pertinents à Resizable

const ResizableSC = styled(({ someProp, ...rest }) => <Resizable {...rest} />)`
    flex: 0 0 ${(props) => props.someProp}px;
`;
25
tskjetne

Pour ceux (comme moi) qui ont atterri ici en raison d'un problème avec SC et react-routerer Link.

C'est fondamentalement la même réponse que @tskjetne, mais avec un style de syntaxe JS.

const StyledLink = styled(({ isCurrent, ...rest }) => <Link {...rest} />)(
  ({ isCurrent }) => ({
    borderBottomColor: isCurrent ? 'green' : 'transparent',
  }),
)
7
Fellow Stranger

Vous pouvez essayer avec defaultProps:

import Resizable from 're-resizable';
import PropTypes from 'prop-types';
...
const ResizableSC = styled(Resizable)``;
export const StyledPaneContainer = ResizableSC.extend`
    flex: 0 0 ${(props) => props.someProp}px;
`;

StyledPaneContainer.defaultProps = { someProp: 1 }

const PaneContainer = ({ children }) => (
    <StyledPaneContainer>
        {children}
    </StyledPaneContainer>
);

export default PaneContainer;

Nous pouvons également passer des accessoires en utilisant 'attrs'. Cela aide à attacher des accessoires supplémentaires (exemple tiré du document officiel des composants stylisés):

const Input = styled.input.attrs({
  // we can define static props
  type: 'password',

  // or we can define dynamic ones
  margin: props => props.size || '1em',
  padding: props => props.size || '1em'
})`
  color: palevioletred;
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;

  /* here we use the dynamically computed props */
  margin: ${props => props.margin};
  padding: ${props => props.padding};
`;

render(
  <div>
    <Input placeholder="A small text input" size="1em" />
    <br />
    <Input placeholder="A bigger text input" size="2em" />
  </div>
); 
0
Chasing Unicorn