Kenneth Beartusk
Kenneth Beartusk

Reputation: 11

Does assigning a JSON object to the style attribute in ReactJS make the object non-configurable

I am trying to dynamically change css styles in my ReactJS application using the "style" attribute. Typically, I assign the attribute to a JSON object, and when I want modify the style attribute based off of a state change in my component. I re-assign the entire JSON object as shown below.

export default class MyClass extends React.Component {

  constructor(props, context) {
    super(props, context);

    this.state = {
      myStyle: {
        marginTop: "100px",
        background: "rgba(0,0,255,0.85)",
        boxShadow: "0px 5px 16px 0px rgba(0,0,0,1)",
      }
    };
  }

  changeStyleFunction() {
    this.setState({
      myStyle: {
        marginTop: "0px",
        background: "rgba(0,0,255,0.85)",
        boxShadow: "0px 5px 16px 0px rgba(0,0,0,1)",
      }
    });
  }

  render() {
    return(
      <div style={myStyle}>
        <button onClick={this.changeStyleFunction.bind(this)}/>
        //some content here
      </div>
    )
  }
}

This works fine, but if I have a JSON object that is 15+ elements, this process turns into a lot of extra code to modify one property. So I decided to take my style object out of the component's state, and use dot notation to modify it as shown below.

let myStyle = {
  marginTop: "100px",
  background: "rgba(0,0,255,0.85)",
  boxShadow: "0px 5px 16px 0px rgba(0,0,0,1)",
};

export default class MyClass extends React.Component {

  changeStyleFunction() {
    myStyle.marginTop = "0px"
    this.forceUpdate();
  }

  render() {
    return(
      <div style={myStyle}>
        <button onClick={this.changeStyleFunction.bind(this)}/>
        //some content here
      </div>
    )
  }
}

Unfortunately, this produces the following error

Uncaught TypeError: Cannot assign to read only property 'marginTop' of object '#<Object>'

So I tried to use Object.defineProperty(myStyle, 'marginTop', {writable: true}) to see if I could force the object to be writable. This only produced another error as shown below.

Uncaught TypeError: Cannot redefine property: marginTop

This only occurs if the object is assigned to the style attribute, which leads me to believe that the underlying ReactJS framework sets the JSON object to be non-configurable if it is assigned to the style attribute. Am I correct? And, how do I circumnavigate this in the future to avoid rewriting large JSON objects in my code?

Upvotes: 1

Views: 1124

Answers (1)

Tholle
Tholle

Reputation: 112917

You're right in that you should not try to mutate the style object directly.

You can modify just one property by spreading the current styles and just changing the one you want to change.

Example (CodeSandbox)

class MyClass extends React.Component {
  state = {
    myStyle: {
      marginTop: "100px",
      background: "rgba(0,0,255,0.85)",
      boxShadow: "0px 5px 16px 0px rgba(0,0,0,1)"
    }
  };

  changeStyleFunction() {
    this.setState(previousState => {
      return {
        myStyle: { ...previousState.myStyle, marginTop: "0px" }
      };
    });
  }

  render() {
    return (
      <div style={this.state.myStyle}>
        <button onClick={this.changeStyleFunction.bind(this)} />
      </div>
    );
  }
}

Upvotes: 0

Related Questions