Reputation: 2277
Disclaimer: I am new to ReactJS
I am trying to implement a dialog window to select a country/language at on the first page of my application.
The idea is the following:
My dialog box initially looks like this:
After clicking on the Vietnamese flag it should changes into this:
After clicking on the country flag, I want two buttons (divs) to appear on the right of the flag so that the user can choose a language. So I am trying to conditionally add the divs based on the current state corresponding to the selected language:
<div className="Country-flag-big" onClick={this.selectCountry("KH")} data-country={"KH"} />
{ this.state.countrySelected==="KH" ? <div className="Language-big" onClick={this.selectLocale} data-locale={"km-KH"} >ភាសាខ្មែរ</div> : null }
{ this.state.countrySelected==="KH" ? <div className="Language-big" onClick={this.selectLocale} data-locale={"en-KH"} >English</div> : null }
However, it does not work, there is an error when the dialog box opens, as if the onClick event was triggered already and creating a conflict:
Warning: setState(...): Cannot update during an existing state transition (such as within
render
or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved tocomponentWillMount
.
Here is the complete component code:
import React from 'react';
import ReactDOM from 'react-dom';
import './CountryFlag.css';
var Dialog = React.createClass({
getInitialState: function () {
return { countrySelected: "" };
},
close(){
ReactDOM.unmountComponentAtNode(this.props.container);
},
componentWillUnmount() {
document.body.removeChild(this.props.container);
},
selectCountry(country) {
console.log('this is c:', country);
this.setState({countrySelected: country});
},
selectLocale() {
console.log('this is:', this);
ReactDOM.unmountComponentAtNode(this.props.container);
},
render(){
return(
<div className="Country-dialog-overlay">
<div className="Country-dialog-inner">
<h2>Country > Language</h2>
<div className="Country-flag-big" onClick={this.selectCountry("KH")} data-country={"KH"} />
{ this.state.countrySelected==="KH" ? <div className="Language-big" onClick={this.selectLocale} data-locale={"km-KH"} >ភាសាខ្មែរ</div> : null }
{ this.state.countrySelected==="KH" ? <div className="Language-big" onClick={this.selectLocale} data-locale={"en-KH"} >English</div> : null }
<div className="Country-flag-big" onClick={this.selectCountry("LA")} data-country={"LA"} />
{ this.state.countrySelected==="LA" ? <div className="Language-big" onClick={this.close} data-locale={"lo-LA"} >ພາສາລາວ</div> : null }
{ this.state.countrySelected==="LA" ?<div className="Language-big" onClick={this.close} data-locale={"en-LA"} >English</div> : null }
<div className="Country-flag-big" onClick={this.selectCountry("MM")} data-country={"MM"} />
{ this.state.countrySelected==="MM" ? <div className="Language-big" onClick={this.close} data-locale={"my-MM"} >မြန်မာ</div> : null }
{ this.state.countrySelected==="MM" ? <div className="Language-big" onClick={this.close} data-locale={"en-MM"} >English</div> : null }
<div className="Country-flag-big" onClick={this.selectCountry("TH")} data-country={"TH"} />
{ this.state.countrySelected==="TH" ? <div className="Language-big" onClick={this.close} data-locale={"th-TH"} >ภาษาไทย</div> : null }
{ this.state.countrySelected==="TH" ? <div className="Language-big" onClick={this.close} data-locale={"en-TH"} >English</div> : null }
<div className="Country-flag-big" onClick={this.selectCountry("VN")} data-country={"VN"} />
{ this.state.countrySelected==="VN" ? <div className="Language-big" onClick={this.close} data-locale={"vi-VN"} >Tiếng việt</div> : null }
{ this.state.countrySelected==="VN" ? <div className="Language-big" onClick={this.close} data-locale={"en-VN"} >English</div> : null }
</div>
</div>
);
}
});
var Trigger = () => {
function showDialog() {
var div = document.createElement('div');
ReactDOM.render(
<Dialog container={div}/>,
document.body.appendChild(div)
);
}
return (
<div className="Country-flag" onClick={showDialog} data-country={"VN"} />
);
};
class CountryFlag extends React.Component {
render() {
return (
<Trigger />
);
}
}
export default CountryFlag;
Any idea why I have this error?
Thanks!
Upvotes: 0
Views: 372
Reputation: 1782
When you do
onClick={this.selectCountry("KH")}
You're actually calling the function, and not storing a reference to the click handler so that it only fires when clicked. You can either do
onClick={() => this.selectCountry("KH")}
or even better, make a bound function that passes in the country name, like so
onClick={this.selectCountry.bind(this, "KH")}
However, since you have data-
attributes in those elements that you're clicking on, you can put just onClick={this.selectCountry}
and in the selectCountry
handler, you can rewrite it like so
selectCountry(e) {
let country = e.currentTarget.dataset.country;
// country will be "KH" for example
}
Upvotes: 1
Reputation: 281626
<div className="Country-flag-big" onClick={this.selectCountry("KH")} data-country={"KH"} />
statement causes the error.
It should be
<div className="Country-flag-big" onClick={() => this.selectCountry("KH")} data-country={"KH"} />
at every place
The reason it did not work in your case is that onClick expects a function but with onClick={this.selectCountry("KH")}
you are actually giving it a value retuned by selectCountry
function. Since you are setting a state in selectCountry
you render is called again and everytime render
is called, selectCountry
is evaluated to return the value to onClick. You need to bind the function in order the pass the value.
You render function will be
render(){
return(
<div className="Country-dialog-overlay">
<div className="Country-dialog-inner">
<h2>Country > Language</h2>
<div className="Country-flag-big" onClick={() => this.selectCountry("KH")} data-country={"KH"} />
{ this.state.countrySelected==="KH" ? <div className="Language-big" onClick={this.selectLocale} data-locale={"km-KH"} >ភាសាខ្មែរ</div> : null }
{ this.state.countrySelected==="KH" ? <div className="Language-big" onClick={this.selectLocale} data-locale={"en-KH"} >English</div> : null }
<div className="Country-flag-big" onClick={() => this.selectCountry("LA")} data-country={"LA"} />
{ this.state.countrySelected==="LA" ? <div className="Language-big" onClick={this.close} data-locale={"lo-LA"} >ພາສາລາວ</div> : null }
{ this.state.countrySelected==="LA" ?<div className="Language-big" onClick={this.close} data-locale={"en-LA"} >English</div> : null }
<div className="Country-flag-big" onClick={() => this.selectCountry("MM")} data-country={"MM"} />
{ this.state.countrySelected==="MM" ? <div className="Language-big" onClick={this.close} data-locale={"my-MM"} >မြန်မာ</div> : null }
{ this.state.countrySelected==="MM" ? <div className="Language-big" onClick={this.close} data-locale={"en-MM"} >English</div> : null }
<div className="Country-flag-big" onClick={() => this.selectCountry("TH")} data-country={"TH"} />
{ this.state.countrySelected==="TH" ? <div className="Language-big" onClick={this.close} data-locale={"th-TH"} >ภาษาไทย</div> : null }
{ this.state.countrySelected==="TH" ? <div className="Language-big" onClick={this.close} data-locale={"en-TH"} >English</div> : null }
<div className="Country-flag-big" onClick={() => this.selectCountry("VN")} data-country={"VN"} />
{ this.state.countrySelected==="VN" ? <div className="Language-big" onClick={this.close} data-locale={"vi-VN"} >Tiếng việt</div> : null }
{ this.state.countrySelected==="VN" ? <div className="Language-big" onClick={this.close} data-locale={"en-VN"} >English</div> : null }
</div>
</div>
);
}
Upvotes: 0