Reputation: 485
I started learning the basics of JS and wrote a small example to examine how buttons work in React using JSX, but I find it to be a bit confusing.
I first create a React component and initialize a variable called bar
with value 'bar'
in the constructor.
I'd like to have this value change to 'baz'
when a button is pressed.
My code looks like this:
<div id="root"></div>
<script type="text/babel">
class Foo extends React.Component {
constructor(props) {
super(props);
this.bar = 'bar'
}
baz(){
this.bar = 'baz'
}
render() {
return (
<div>
<button onClick={this.baz()}>baz</button>
<p>{this.bar}</p>
</div>
);
}
}
ReactDOM.render(
<Foo />,
document.getElementById('root')
);
</script>
Contrary to my expectations, the value 'baz'
is shown right away when I load the page containing this code in my browser.
I'm sorry for asking a probably very newbie question, but I don't understand why 'baz'
is shown right away, instead of only after I pressed the button. Thank you for your time. :)
Upvotes: 4
Views: 12444
Reputation: 632
You need to store your values in state, and then bind you click handler to the component. Then use setState()
to change the value of state. When state changes, your component will re-render:
class Foo extends React.Component {
constructor () {
super()
this.state = {
bar: 'bar'
}
this.handleClick = this.handleClick.bind(this)
}
handleClick () {
this.setState({
bar: 'baz'
})
}
render () {
return (
<div>
<button onClick={this.handleClick}>baz</button>
<p>{this.state.bar}</p>
</div>
)
}
}
Upvotes: 0
Reputation: 129
import React, { Component } from "react";
class Bar extends Component {
constructor(props) {
super(props);
this.state = {
bar: "bar"
};
}
handleClick = () => {
this.setState({ bar: "baz" });
};
render() {
const value = this.state.bar;
return (
<div>
<button onClick={this.handleClick}>baz</button>
<p>{value}</p>
</div>
);
}
}
A couple of things :
Upvotes: 0
Reputation: 641
You're calling the baz
function during the render, that's why the change happens immediately:
<button onClick={this.baz()}>baz</button>
If you pass a function instead of calling a function, the function will get called when the button is pressed instead:
<button onClick={() => this.baz()}>baz</button>
Upvotes: 0
Reputation: 6914
You can try this:
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = { text: "bar" };
}
baz() {
this.setState({ text: "baz" });
}
render() {
return (
<div>
<button onClick={() => this.baz()}>baz</button>
<p>{this.state.text}</p>
</div>
);
}
}
ReactDOM.render(<Foo />, document.getElementById("root"));
The thing is to update the screen (DOM) its better to change state to let the component re-render. And for the problem that value was initially changed , other answers explain them well
Upvotes: 6
Reputation: 20911
I pointed out the solution in a comment above, so, I'll thresh out that comment a bit more...
You have...
<button onClick={this.baz()}>baz</button>
You want...
<button onClick={() => this.baz()}>baz</button>
I have also threshed out the rest of your code to produce the result you wanted ("I'd like to have this value change to 'baz' when a button is pressed."). You also needed...
this.setState(this);
See a full working example here:
https://codesandbox.io/s/vj904qy4o0
Upvotes: 1
Reputation: 2646
The way you are trying to use function is incorrect. Refer to one of the below two methods. Also, bind your function to this context in the constructor.
this.baz = this.baz.bind(this);
Then
onClick={this.baz}
OR
onClick={() => this.baz()}
Upvotes: 2
Reputation: 1381
The reason baz
is shown right away is because you're calling the function in the click binding. You should also bind your click handler to your React class. Here's an example of how this should look:
<div id="root"></div>
<script type="text/babel">
class Foo extends React.Component {
constructor(props) {
super(props);
this.bar = 'bar';
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.bar = 'baz';
}
render() {
return (
<div>
<button onClick={this.handleClick}>baz</button>
<p>{this.bar}</p>
</div>
);
}
}
ReactDOM.render(
<Foo />,
document.getElementById('root')
);
</script>
Upvotes: 0