I want to change the style of a component's element on some event, like a click. But when i do, i get the error that my style object is read-only when its not defined as such and thus immutable. Even defining the style object outside the class creates the same error. I created a simple example to illustrate my problem below.
Error:
Uncaught TypeError: Cannot assign to read only property 'color' of object '#<Object>'
profile.tsx
import * as React from 'react';
export default class Profile extends React.Component {
public styler = {
color:"white",
}
render() {
return (<button style={this.styler} onClick={this.HandleMenuClick.bind(this)}>Click me!</button>);
}
HandleMenuClick() {
this.styler.color = 'gray'; // error on executing this line
}
}
Error created upon clicking the button.
Same error is created when moving the style outside of the class:
var styler = {
color:"white",
}
You should use the this
key word when inside a class. But to see changes in react you should use a state
.
Here is a small example:
class Profile extends React.Component {
constructor(props) {
super(props);
this.state = {
styler:{
color: "white"
}
}
}
render() {
const {styler} = this.state;
return (
<button style={styler} onClick={this.HandleMenuClick}>
Click me!
</button>
);
}
HandleMenuClick = () => {
const { styler } = this.state;
this.setState({styler: {
...styler,
color: 'gray',
backgroundColor: '#000'
}})
};
}
ReactDOM.render(<Profile />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Edit
As a followup to your comment:
But out of curiosity, my this.styler.color variable never changes in code, i know it wont call render but it doesnt even change the variable in code and just gives the error, why is that?
As i mentioned above, you should use the this
key word to attach objects to the class
which basically just a sugar around the prototype pattern
JavaScript classes are introduced in ECMAScript 6 and are syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance.
In your code you used the public
key word which i'm not familiar with in this context (is it a typo?) + you should initialize objects inside the constructor
.
here is an example with the object being mutated:
class Profile extends React.Component {
constructor(props) {
super(props);
this.myObject = {
myKey: "Hi there!"
};
}
render() {
return <button onClick={this.HandleMenuClick}>Click me!</button>;
}
HandleMenuClick = () => {
console.log(this.myObject);
this.myObject = {
myKey: "Bye there!"
};
console.log(this.myObject);
};
}
ReactDOM.render(<Profile />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>