How to combine multiple inline style objects?

In React you can clearly create an object and assign it as an inline style. i.e.. mentioned below.

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

How can I combine multiple objects and assign them together?


Solution 1:

If you're using React Native, you can use the array notation:

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

Check out my detailed blog post about this.

Solution 2:

You can use the spread operator:

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

Solution 3:

You can do this with Object.assign().

In your example, you would do:

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

That will merge the two styles. The second style will replace the first if there are matching properties.

As Brandon noted, you should use Object.assign({}, divStyle, divStyle2) if you want to reuse divStyle without the fontSize applied to it.

I like to use this to make components with default properties. For example, here's a little stateless component with a default margin-right:

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

So we can render something like this:

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

Which will give us the result:

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

Solution 4:

Unlike React Native, we cannot pass array of styles in React, like

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

In React, we need to create the single object of styles before passing it to style property. Like:

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

  let enhancedStyle = {
    fontSize: '38px'
  }

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

We have used ES6 Spread operator to combine two styles. You can also use Object.assign() as well for the same purpose.

This also works if you don't need to store your style in a var

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

Solution 5:

Object.assign() is an easy solution, but the (currently) top answer's usage of it — while just fine for making stateless components, will cause problems for the OP's desired objective of merging two state objects.

With two arguments, Object.assign() will actually mutate the first object in-place, affecting future instantiations.

Ex:

Consider two possible style configs for a box:

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

So we want all our boxes to have default 'box' styles, but want to overwrite some with a different color:

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

Once Object.assign() executes, the 'styles.box' object is changed for good.

The solution is to pass an empty object to Object.assign(). In so doing, you're telling the method to produce a NEW object with the objects you pass it. Like so:

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

This notion of objects mutating in-place is critical for React, and proper use of Object.assign() is really helpful for using libraries like Redux.