複数のインラインスタイルオブジェクトを組み合わせる方法は?


213

Reactでは、オブジェクトを明確に作成して、インラインスタイルとして割り当てることができます。すなわち。後述します。

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);

複数のオブジェクトを結合して一緒に割り当てるにはどうすればよいですか?


2つのオブジェクトはどのように見えますか?
ライアン

回答:


396

React Nativeを使用している場合は、配列表記を使用できます。

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

これに関する私の詳細なブログ投稿をチェックしてください。


41
残念ながら、通常のReactではこれを行うことはできません。
YoTengoUnLCD

8
React-Native
calcazar

スタイル名/値を追加することにより、既存のインラインスタイルをわずかに変更できます。例えば、<View style={this.state.error == false ? styles.base : [styles.base, {backgroundColor: 'red'}]} />
GürolCanbek

2つの静的スタイルの場合StyleSheet.compose()、render関数の外側で行う方が効率的です。これは、ブリッジを介して1回だけ送信される新しい静的スタイルシートを生成します。(このアドバイスは、実行時に変更されるスタイル、またはStyleSheetの代わりにインラインであるスタイルには適用されません。)
joeytwiddle

282

スプレッド演算子を使用できます。

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

8
最初のスプレッド演算子の最初のドットを指す「構文エラー:予期しないトークン」が表示されます。
イズカタ2016

反応またはネイティブ反応に@Izkataは、あなたがあなたのスニペット投稿することができ、これをやっている
ナス

リアクト、それは何かのようなものだった<div style={{ ...LEGEND_STYLE.box_base, ...{ 'background': '#123456' } }} />
イズカタ

私のようなヘルパー関数を使用するためにとにかくそれを変更し<div style={LEGEND_STYLE.box_gen('#123456')}、それは私には大したことではありませんので、とにかく
Izkata

これは、オブジェクトがキーと値のペアを1つだけ持っている場合でも機能します。ただし、スプレッド演算子はイテラブルに対してのみ有効であると想定されています。理由を説明できますか?developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
タイラー

47

これはで行えますObject.assign()

あなたの例では、あなたはそうするでしょう:

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

2つのスタイルがマージされます。一致するプロパティがある場合、2番目のスタイルが最初のスタイルを置き換えます。

Brandonが述べたように、fontSizeを適用せずObject.assign({}, divStyle, divStyle2)に再利用する場合に使用する必要がありますdivStyle

これを使用して、デフォルトのプロパティを持つコンポーネントを作成します。たとえば、以下はデフォルトの小さなステートレスコンポーネントですmargin-right

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

したがって、次のようにレンダリングできます。

<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>

結果は次のようになります。

<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>

5
このソリューションはObject.assign()、いくつかの望ましくない結果につながるような方法で潜在的に誤用されています。より信頼性の高いソリューションについては、こちらの回答をご覧ください。
Brandon

1
あなたの答えは、Object.assign()を誤用する方法を示しています。これは一部の人にとっては役立つ情報かもしれませんが、私の例には当てはまりません。この例では、デフォルトをオブジェクトに格納せず、それを変更して、変更されたオブジェクトを別の場所で再利用しています。
2016年

同意しない。Object.assign()回答で使用する2つの個別の方法に対処します。最初の数文の最初の部分は、私が特定した誤用の例です(つまり、OPが最初のcodeブロックでアドバイスしたことをした場合、彼/彼女は変異します{divStyle})。2番目の方法、つまり、関数でそれをラップすることは機能しますが、答えは、一般的な 'gotcha' wrt不変性を回避 していることを明確にしませんObject.assign()(個人的には少し小さいと思いますがデフォルトのコンポーネントごとにカスタムのステートレス関数を記述するのは面倒です)。
Brandon

ああ、そう。それは本当だ。fontSizeを適用せずにdivStyleを再利用したい場合は、最初に空のオブジェクトが必要です。答えを更新します。
qel

Object.assign()は、連結を実現するための最も便利な方法です:)
aldobsom

29

React Nativeとは異なり、Reactでは次のようにスタイルの配列を渡すことができません。

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

Reactでは、styleプロパティに渡す前に、スタイルの単一オブジェクトを作成する必要があります。お気に入り:

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

  let enhancedStyle = {
    fontSize: '38px'
  }

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

ES6 Spreadオペレーターを使用して、2つのスタイルを組み合わせました。同じ目的でObject.assign()を使用することもできます。

これは、varにスタイルを保存する必要がない場合にも機能します

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

配列をスタイルに渡すことはできませんか?
ハイゼンベルグ2018年

3
最後のスニペットに追加するだけで、{{... segmentStyle、height: '100%'}}も機能します。
ルークブランドンファレル

26

Object.assign()は簡単な解決策ですが、(現在の)トップアンサーの使用法—ステートレスコンポーネントを作成するのは問題ありませんが、2つのstateオブジェクトをマージするというOPの望ましい目的に対して問題が発生します。

2つの引数を指定Object.assign()すると、最初のオブジェクトが実際に変更され、将来のインスタンス化に影響します。

例:

ボックスの2つの可能なスタイル構成を検討してください。

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

したがって、すべてのボックスにデフォルトの「ボックス」スタイルを設定し、一部を別の色で上書きしたいとします。

// 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>

一度Object.assign()実行し、「styles.box」オブジェクトは永久に変更されます。

解決策は、空のオブジェクトをに渡すことObject.assign()です。そうすることで、渡したオブジェクトを使用してNEWオブジェクトを生成するようにメソッドに指示しています。そのようです:

// 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>

オブジェクトがインプレースで変化するというこの概念はReactにとって重要であり、適切に使用することはObject.assign()Reduxのようなライブラリーを使用するのに非常に役立ちます。


1
Object.assignを誤用する方法の例は、Object.assignが(現在)上位の回答でどのように使用されているかを示す有効な表現ではありません。
2016年

おかげで、どの側面が(現在)誤用であるかを反映するように編集
Brandon

1
素敵なコードがすぐそこにあります。Object.assign({}、this.state.showStartOverBtn?{}:this.hidden、this.btnStyle)}条件文もチャームのように機能します
steveinatorx

17

配列表記は、reactネイティブでスタイルを組み合わせる最良の方法です。

これは、2つのStyleオブジェクトを組み合わせる方法を示しています。

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

これは、Styleオブジェクトとプロパティを組み合わせる方法を示しています。

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

これは、すべての反応ネイティブアプリケーションで機能します。


2
質問はのためReactではなくReact Native
Dimitar Tsonev

同じことをReactにも使用できます
Sasindu Lakshitha

Reactは最初から配列をサポートしていませんが、現在は機能していません。
witoong623

このような組み合わせスタイルはまだサポートされていません。
怒ったキウイ

12

次のように、クラスをインラインスタイルと組み合わせることもできます。

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

8

実際には、正式に組み合わせる方法があり、以下のようになります。

<View style={[style01, style02]} />

しかし、小さな問題があります。それらの1つが親コンポーネントによって渡され、それが結合された形式的な方法で作成された場合、大きな問題があります。

// The passing style02 from props: [parentStyle01, parentStyle02]

// Now:
<View style={[style01, [parentStyle01, parentStyle02]]} />

そして、この最後の行はUIバグの原因になります。当然、React Nativeは配列内の深い配列を処理できません。だから私は私のヘルパー関数を作成します:

import { StyleSheet } from 'react-native';

const styleJoiner = (...arg) => StyleSheet.flatten(arg);

私のstyleJoiner場所を使用することで、あらゆるタイプのスタイルを組み合わせたり、スタイルを組み合わせることができます。でも、undefinedまたは他の無用のタイプはスタイリングを壊すことはありません。



2

Reactでこのソリューションを探している人のために、spreadオペレーターをスタイル内で使用したい場合は、babel-plugin-transform-object-rest-spreadを使用する必要があります。

npmモジュールでインストールし、.babelrcを次のように設定します。

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

次に、次のように使用できます...

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

詳細:https : //babeljs.io/docs/en/babel-plugin-transform-object-rest-spread/


2

これをさらに進めるには、クラス名のようなヘルパー関数を作成します。

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

そして、それをコンポーネントで条件付きで使用します。

<div style={

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

}>Hello World!</div>

0

だから基本的に私はこれを間違った方法で見ています。私が見る限り、これはReact固有の質問ではなく、2つのJavaScriptオブジェクトをどのように結合するか(同様の名前のプロパティを壊さないで)のJavaScript質問の詳細です。

このStackOverflowの回答では、それについて説明しています。 2つのJavaScriptオブジェクトのプロパティを動的にマージするにはどうすればよいですか?

jQueryでは、extendメソッドを使用できます。


1
CSSスタイルを含むオブジェクトを操作する場合、オブジェクトをマージするだけでは不十分です。マージ機能によって正しい順序で処理する必要がある省略形のプロパティ、異なる文字の大文字小文字などがあります。そのような機能を提供するライブラリを探していて、まだ見つけていません。
sompylasar 2015

以下は、プロパティの省略表現を行うライブラリです:github.com/kapetan/css-shorthand-expandですが、これは完全なソリューションではありません。
sompylasar 2015

0

@PythonIsGreatが言ったことを拡張するために、私はそれを行うグローバル関数を作成します。

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

これは、オブジェクトを新しいオブジェクトに深く拡張し、パラメーターとして可変数のオブジェクトを許可します。これにより、次のようなことが可能になります。

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

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

CSSスタイルを含むオブジェクトを操作する場合、単純なオブジェクトマージ機能では不十分です。上記の回答に対する私のコメントを参照してください。
sompylasar 2015


0

インラインスタイルの方法:

<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>

3
Reactは最初から配列をサポートしていませんが、現在は機能していません。
witoong623
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.