web-dev-qa-db-fra.com

Comment combiner plusieurs objets de style en ligne?

Dans React, vous pouvez clairement créer un objet et l’affecter à un style incorporé. i.e .. mentionné ci-dessous. 

var divStyle = {
  color: 'white',
  backgroundImage: 'url(' + imgUrl + ')',
  WebkitTransition: 'all', // note the capital 'W' here
  msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};

var divStyle2 = {fontSize: '18px'};

React.render(<div style={divStyle}>Hello World!</div>, mountNode);

Comment combiner plusieurs objets et les assigner ensemble? 

132
PythonIsGreat

Si vous utilisez React Native, vous pouvez utiliser la notation array:

<View style={[styles.base, styles.background]} />

Voir le docs pour plus d’informations.

274
Nick

Vous pouvez utiliser l'opérateur spread:

 <button style={{...styles.panel.button,...styles.panel.backButton}}>Back</button
221
Nath

Vous pouvez le faire avec Object.assign().

Dans votre exemple, vous feriez:

ReactDOM.render(
    <div style={Object.assign(divStyle, divStyle2)}>
        Hello World!
    </div>,
    mountNode
);

Cela va fusionner les deux styles. Le second style remplacera le premier s'il existe des propriétés correspondantes.

Comme l'a souligné Brandon, vous devez utiliser Object.assign({}, divStyle, divStyle2) si vous souhaitez réutiliser divStyle sans que la valeur de fontSize y soit appliquée.

J'aime utiliser ceci pour créer des composants avec des propriétés par défaut. Par exemple, voici un petit composant sans état avec un margin-right par défaut:

const DivWithDefaults = ({ style, children, ...otherProps }) =>
    <div style={Object.assign({ marginRight: "1.5em" }, style)} {...otherProps}>
        {children}
    </div>;

Nous pouvons donc rendre quelque chose comme ceci:

<DivWithDefaults>
    Some text.
</DivWithDefaults>
<DivWithDefaults className="someClass" style={{ width: "50%" }}>
    Some more text.
</DivWithDefaults>
<DivWithDefaults id="someID" style={{ marginRight: "10px", height: "20px"}}>
    Even more text.
</DivWithDefaults>

Ce qui nous donnera le résultat:

<div style="margin-right:1.5em;">Some text.</div>
<div style="margin-right:1.5em;width50%;" class="someClass">Some more text.</div>
<div style="margin-right:10px;height:20px;" id="someID">Even more text.</div>
37
qel

Object.assign() est une solution facile, mais son utilisation (actuelle) par top answer - bien que très bien pour créer des composants sans état, posera des problèmes pour l'objectif souhaité par le PO de fusionner deux objets state.

Avec deux arguments, Object.assign() mutera réellement le premier objet sur place, ce qui affectera les instanciations futures.

Ex:

Considérez deux configurations de style possibles pour une boîte: 

var styles =  {
  box: {backgroundColor: 'yellow', height: '100px', width: '200px'},
  boxA: {backgroundColor: 'blue'},
};

Nous voulons donc que toutes nos boîtes aient des styles par défaut, mais nous souhaitons en remplacer certaines avec une couleur différente:

// this will be yellow
<div style={styles.box}></div>

// this will be blue
<div style={Object.assign(styles.box, styles.boxA)}></div>

// this SHOULD be yellow, but it's blue.
<div style={styles.box}></div>

Une fois que Object.assign() est exécuté, l'objet 'styles.box' est définitivement modifié.

La solution consiste à passer un objet vide à Object.assign(). Ce faisant, vous indiquez à la méthode de produire un objet NEW avec les objets que vous lui transmettez. Ainsi:

// this will be yellow
<div style={styles.box}></div>

// this will be blue
<div style={Object.assign({}, styles.box, styles.boxA)}></div>

// a beautiful yellow
<div style={styles.box}></div>

Cette notion de mutation in situ des objets est essentielle pour React, et l'utilisation correcte de Object.assign() est très utile pour l'utilisation de bibliothèques telles que Redux.

19
Brandon

Contrairement à React Native, nous ne pouvons pas transmettre un tableau de styles dans React, comme

<View style={[style1, style2]} />

Dans React, nous devons créer l'objet unique de styles avant de le transmettre à la propriété style. Comme:

const Header = (props) => {
  let baseStyle = {
    color: 'red',
  }

  let enhancedStyle = {
    fontSize: '38px'
  }

  return(
    <h1 style={{...baseStyle, ...enhancedStyle}}>{props.title}</h1>
  );
}

Nous avons utilisé ES6 Opérateur Spread pour combiner deux styles. Vous pouvez également utiliser Object.assign () dans le même but.

Cela fonctionne aussi si vous n'avez pas besoin de stocker votre style dans une var

<Segment style={{...segmentStyle, ...{height:'100%'}}}>
    Your content
</Segment>
18
achyut pokhrel

Vous pouvez également combiner des classes avec un style en ligne comme ceci:

<View style={[className, {paddingTop: 25}]}>
  <Text>Some Text</Text>
</View>
11
Gil Perez

Array notaion est le meilleur moyen de combiner les styles en natif.

Cela montre comment combiner 2 objets de style,

<Text style={[styles.base, styles.background]} >Test </Text>

cela montre comment combiner l'objet et la propriété Style,

<Text style={[styles.base, {color: 'red'}]} >Test </Text>

Cela fonctionnera sur n'importe quelle application native native.

5
Sasindu Lakshitha

Façons de style inline:

<View style={[styles.red, {fontSize: 25}]}>
  <Text>Hello World</Text>
</View>

<View style={[styles.red, styles.blue]}>
  <Text>Hello World</Text>
</View>

  <View style={{fontSize:10,marginTop:10}}>
  <Text>Hello World</Text>
</View>
2
him

Pour aller plus loin, vous pouvez créer une fonction d'assistance semblable à classnames :

const styleRules = (...rules) => {
  return rules.filter(Boolean).reduce((result, rule) => {
    return { ...result, ...rule };
  }, {});
};

Et utilisez-le ensuite de manière conditionnelle dans vos composants:

<div style={

  styleRules(
    divStyle,
    (window.innerWidth >= 768) && divStyleMd,
    (window.innerWidth < 768) && divStyleSm
  )

}>Hello World!</div>
1
streletss

Pour développer ce que @PythonIsGreat a dit, je crée une fonction globale qui le fera pour moi:

var css = function(){
    var args = $.merge([true, {}], Array.prototype.splice.call(arguments, 0));
    return $.extend.apply(null, args);
}

Cela étend profondément les objets dans un nouvel objet et permet un nombre variable d'objets en tant que paramètres. Cela vous permet de faire quelque chose comme ceci:

return(
<div style={css(styles.base, styles.first, styles.second,...)} ></div>
);

var styles = {
  base:{
    //whatever
  },
  first:{
    //whatever
  },
  second:{
    //whatever
  }
}
0
timthez

Pour ceux qui recherchent cette solution dans React, si vous souhaitez utiliser l'opérateur spread à l'intérieur du style, vous devez utiliser: babel-plugin-transform-object-rest-prop-spread.

Installez-le avec le module npm et configurez votre .babelrc en tant que tel:

{
  "presets": ["env", "react"],
  "plugins": ["transform-object-rest-spread"]
}

Ensuite, vous pouvez utiliser comme ...

const sizing = { width: 200, height: 200 }
 <div
   className="dragon-avatar-image-background"
   style={{ backgroundColor: blue, ...sizing }}
  />

Plus d'infos: https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread/

0

Donc, fondamentalement, je regarde cela de la mauvaise façon. D'après ce que je vois, ce n'est pas une question spécifique de React, mais plutôt une question de JavaScript expliquant comment combiner deux objets JavaScript (sans masquer les propriétés de même nom). 

Dans cette réponse StackOverflow, il l'explique. Comment puis-je fusionner les propriétés de deux objets JavaScript dynamiquement?

Dans jQuery, je peux utiliser la méthode extend. 

0
PythonIsGreat

J'ai construit un module pour cela si vous voulez ajouter des styles en fonction d'une condition.

multipleStyles(styles.icon, { [styles.iconRed]: true })

https://www.npmjs.com/package/react-native-multiple-styles

0
dubbelnisse