Reputation: 31
I am very new in the world of React, so I am not sure what I am doing wrong. I have a click handler in parent component which needs to be passed the button element of child component.
Parent Component is 'LogStatus'
import React, { Component } from 'react';
import DisplayMessage from './DisplayMessage'
class LogStatus extends React.Component {
constructor(props) {
super(props);
this.state = {
isLogin: true,
}
this.btnChangeStatusClickHandler = this.btnChangeStatusClickHandler.bind(this);
}
btnChangeStatusClickHandler() {
this.setState(previousState =>
previousState.isLogin = !this.state.isLogin,
)
}
render() {
let statusMessage = '';
if (this.state.isLogin === true) {
statusMessage = 'Login';
}
else {
statusMessage = 'Logoff'
}
return (
<div>
<DisplayMessage statusMessage={statusMessage} loginStatusHandler={this.btnChangeStatusClickHandler} />
</div>
);
}
}
export default LogStatus;
Child Component is 'DisplayMessage'
import React, { Component } from 'react';
class DisplayMessage extends Component {
constructor(props) {
super(props);
this.state = {
statusMessage: props.statusMessage,
btnStatusClickHandler: props.loginStatusHandler,
}
}
render() {
let displayBtnMessage = '';
if (this.state.statusMessage === 'Login') {
displayBtnMessage = "Logoff";
}
else {
displayBtnMessage = 'Login';
}
return (
<div>
<h3>Login Status: {this.state.statusMessage}</h3>
<button onClick={this.state.btnStatusClickHandler}>{displayBtnMessage}</button>
</div>
);
}
}
export default DisplayMessage;
Working Code for the reference:
Parent Component is 'LogStatus'
import React, { Component } from 'react';
import DisplayMessage from './DisplayMessage'
class LogStatus extends React.Component {
constructor(props) {
super(props);
this.state = {
isLogin: true,
displayStatus: '',
}
this.btnChangeStatusClickHandler = this.btnChangeStatusClickHandler.bind(this);
}
btnChangeStatusClickHandler() {
this.setState(previousState => {
if (this.state.isLogin === true) {
return {
displayStatus: 'Login',
isLogin: !previousState.isLogin,
}
}
else {
return {
displayStatus: 'Logoff',
isLogin: !previousState.isLogin,
}
}
})
}
render() {
return (
<div>
<DisplayMessage statusMessage={this.state.displayStatus} loginStatusHandler={this.btnChangeStatusClickHandler} />
</div>
);
}
}
export default LogStatus;
Child Component is 'DisplayMessage'
import React, { Component } from 'react';
class DisplayMessage extends Component {
render() {
const { statusMessage, loginStatusHandler } = this.props;
let displayBtnMessage = '';
if (statusMessage === 'Login') {
displayBtnMessage = "Logoff";
}
else {
displayBtnMessage = 'Login';
}
return (
<div>
<h3>Login Status: {statusMessage}</h3>
<button onClick={loginStatusHandler}>{displayBtnMessage}</button>
</div>
);
}
}
export default DisplayMessage;
Upvotes: 1
Views: 56
Reputation: 6631
You need two changes in your code;
You btnChangeStatusClickHandler
is currently a method of your class component. However, calling this function will use a global context (this). So this.setState
will not work. You can fix this by turning the method in an arrow function member instead:
Change:
btnChangeStatusClickHandler() {
this.setState(previousState =>
previousState.isLogin = !this.state.isLogin,
)
}
To:
btnChangeStatusClickHandler = () => {
this.setState(previousState =>
previousState.isLogin = !this.state.isLogin,
)
}
It is not needed (and not recommended) to delegate your click handler and other props in the component state. You should always use event handlers and other properties from props
directly so it can deal with changes.
import React, { Component } from 'react';
class DisplayMessage extends Component {
render() {
const { statusMessage, loginStatusHandler } = this.props;
let displayBtnMessage = '';
if (statusMessage === 'Login') {
displayBtnMessage = "Logoff";
}
else {
displayBtnMessage = 'Login';
}
return (
<div>
<h3>Login Status: {statusMessage}</h3>
<button onClick={loginStatusHandler}>{displayBtnMessage}</button>
</div>
);
}
}
export default DisplayMessage;
Upvotes: 1