Here we are going to use the modal component from materialize css to add comments on a wine
For this step you'll need to add comments
to the API exposed at https://wines-api.herokuapp.com
.
The URL you need are the following
POST https://wines-api.herokuapp.com/api/wines/:id/comments
=> add a comment on the wine
Obviously, you'll need to add the following functions to the module responsible for calling the API
export function commentWine(id, content) {
return fetch(`${host}/api/wines/${id}/comments`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ title: 'The title', content })
});
}
the comment button is a very simple component, its only job is to trigger the <CommentModal />
component opening through a function call
The contract of <CommentButton />
is the following
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export class CommentButton extends Component {
static propTypes = {
openCommentModal: PropTypes.func
};
...
}
the view of <CommentButton />
component will look something like
<a class="waves-effect waves-teal btn-flat">
Comment <i class="material-icons left">comment</i>
</a>
The <CommentModal />
component is a modal from materialize css. This component will have an input text for the comment content and some buttons to validate or cancel the comment.
The only issue is that the materialize css modal component is using jQuery
to work. So we will need to use some special feature of React to deal with that.
The contract of <CommentModal />
is the following
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export class CommentModal extends Component {
static propTypes = {
isOpen: PropTypes.bool
};
state = {
comment: ''
};
componentDidMount() {
// if this.props.isOpen then open the modal on mount
}
componentWillUnmount() {
// close the modal
}
componentWillReceiveProps(nextProps) {
// if nextProps.isOpen !== this.props.isOpen, open or close modal according to the new value
}
...
});
the view of <CommentModal />
component will look something like
<div class="modal">
<div class="modal-content">
<h4>Tell us something about this wine</h4>
<form class="col s12">
<div class="row">
<div class="input-field col s12">
<input id="inputComment" type="text" class="validate"/>
<label htmlFor="inputComment">Your comment</label>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<a href="#!" class="modal-action waves-effect waves-green btn-flat">Submit</a>
<a href="#!" class="modal-action waves-effect waves-green btn-flat">Cancel</a>
</div>
</div>
According to the documentation of materialize css modal component to open or close a modal you need to do the following code
window.$(theDomNodeOfTheModal).openModal(); // open the modal
window.$(theDomNodeOfTheModal).closeModal(); // close the modal
to use this code inside a our React component, we need to get a reference to the actual DOM node generated by React (the one with the modal
class).
To do that we are going to use React refs
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export class CommentModal extends Component {
...
render() {
// here we set the value of this.modalNode to the actual ref to the DOM node
// ||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvv
return (
<div className="modal" ref={ref => this.modalNode = ref}>
<div className="modal-content">
<h4>Tell us something about this wine</h4>
<form className="col s12">
<div className="row">
<div className="input-field col s12">
<input id="inputComment" type="text" className="validate"/>
<label htmlFor="inputComment">Your comment</label>
</div>
</div>
</form>
</div>
<div className="modal-footer">
<a href="#!" className="modal-action waves-effect waves-green btn-flat">Submit</a>
<a href="#!" className="modal-action waves-effect waves-green btn-flat">Cancel</a>
</div>
</div>
);
}
}
using the ref trick, you can now access this.modalNode
inside your code, so you can use code like
window.$(this.modalNode).openModal(); // open the modal
window.$(this.modalNode).closeModal(); // close the modal
And now your wine details component should look something like that
react-101
is now over. See you soon for react-102
;-)