Thuong Nguyen Thuong Nguyen - 2 months ago 22
React JSX Question

ReactJS set state of another class through props callback

I am trying to make fullcalendar play nice with ReactJS and Bootstrap modal.
What I want is whenever user choose a date, a bootstrap modal will appear with selected date.

https://jsfiddle.net/16j1se1q/1/


This is my code

class Application extends React.Component {
render() {
return (
<FullCalendar />
);
}
}

class FullCalendar extends React.Component {
constructor(props) {
super(props);
this.state = {view: {showModal: false}};
}

handleHideModal(){
this.setState({view: {showModal: false}})
}

handleShowModal(){
this.setState({view: {showModal: true}})
}

render() {
return (
<div>
<div is id="calendar" class="bootswatch-flatly"></div>
{this.state.view.showModal ? <AppointmentPopup handleHideModal={this.handleHideModal}/> : null}
</div>
);
}

componentDidMount() {
var _that = this;
$('#calendar').fullCalendar({
/* ... */
dayClick: function(date, jsEvent, view) {
/* ... */
_that.handleShowModal();
}
});
}

componentWillUnmount() {
$('#calendar').fullCalendar('destroy');
}
}

class AppointmentPopup extends React.Component {
htmlTemplate() {
return (
/* ... */
)
}

render() {
return this.htmlTemplate();
}

componentDidMount() {
var _that = this;
$('.appointment-modal').modal({
show: true,
keyboard: false,
backdrop: 'static'
}).on('hide.bs.modal', function(e) {
/* ... */
});
$('.appointment-modal').on('hidden.bs.modal', this.props.handleHideModal);
}
propTypes:{
handleHideModal: React.PropTypes.func.isRequired
}
}


ReactDOM.render(<Application />, document.getElementById('app'));


My full source code is at:
http://pastebin.com/MZbVqYFZ


It works fine until I click on a date then close modal.
The problem was caused because that state view.showModal didn't change.
I got the error:
this.setState is not a function

It seems that
this.props.handleHideModal
was called successfully but somehow
this
is not ReactJS object

Answer

ReactJS used to automatically bind the component to the method for you. But with es6 style components you're expected to do it yourself as in:

render() {
    return (
        <div>
            <div is id="calendar" class="bootswatch-flatly"></div>
            {this.state.view.showModal ? <AppointmentPopup handleHideModal={this.handleHideModal.bind(this)}/> : null}
        </div>
    );
}