I'm having trouble showing a modal dialog with loading message during ajax request(with superagent).
I have a reactjs app that has a single input field, a button, and a modal region. I want it to work like so...
A user inserts a keyword into the input field and clicks on the button.
Once the button has been clicked, an ajax call is made to scrape information from a certain website using the keyword.
During the ajax call, a modal dialog that shows a loading message appears.
Once the the ajax call is over, the modal dialog is closed and a list of information that has been scraped will be listed under the input field.
I can't seem to get 3. to work.
Here's what I have: I tried putting in a method that changes the props of the modal component before and after the ajax call that didn't work.
Any help is appreciated!
app.js
import React from 'react'
import ReactDOM from 'react-dom'
import PageBody from './pageBody'
ReactDOM.render(
<PageBody />
,document.getElementById('root')
)
pageBody.js
import React, {Component} from 'react'
import Search from './Search'
import Modal from './modal'
export default class PageBody extends Component{
constructor (props){
super(props)
this.state = {
is_crawling: false
}
}
crawlState (is_crawling) {
this.setState({is_crawling: is_crawling})
}
render () {
const show_modal = this.state.is_crawling
this.crawlState = this.crawlState.bind(this)
return (
<div>
<Search crawlState={this.crawlState}/>
<Modal show_modal={show_modal}/>
</div>
)
}
}
search.js
import React, {Component} from 'react'
import request from 'superagent'
export default class Search extends Component{
constructor (props) {
super(props)
this.state = {
keyword: ''
,result: []
}
}
// method used to make ajax request
crawl (){
const keyword = this.state.keyword
this.props.crawlState(true) // set crawlstate as true to show modal
request // actual ajax request (superagent)
.get('/crawl')
.query({keyword: keyword})
.end((err, res) => {
if (err) console.log('superagent failed')
const r = res.body.result
this.setState({result: r})
})
this.props.crawlState(false) // set crawlstate as false to hide modal
}
onChangeHandler (e) {
this.setState({keyword: e.target.value})
}
render () {
const onChangeHandler = e => this.onChangeHandler(e)
const crawl = this.crawl()
const keyword = this.state.keyword
const arr = this.state.result.map((e, idx) => {
return <div key={idx}>{e}</div>
})
return (
<div>
<input type="text" onChange={onChangeHandler} value={keyword} />
<button onClick={crawl}>CRAWL</button>
{arr}
</div>
)
}
}
modal.js
import React, {Component} from 'react'
export default class Modal extends Component{
constructor (props) {
super(props)
this.state = {
show: false
}
}
componentWillReceiveProps(nextProps){
const show_modal = nextProps.show_modal
this.setState({show: show_modal})
}
render () {
if (this.state.show){
return <div id="modal"></div>
} else {
return null
}
}
}
In pageBody.js
component,you should bind crawlState()
function inside the constructor not inside the render or you can use arrow function like crawlState = () => {}
In search.js
component, use this.crawl
on onClick
function rather than making new const variable.
You should bind crawl
function to use this
inside the function and you have called this.props crawlState()
in the same level without any conditions which means you have called setState()
twice at the same time which you shouldn't do, so you should call this.props crawlState(false)
inside end
after the request completion.
pageBody.js
import React, {Component} from 'react'
import Search from './Search'
import Modal from './modal'
export default class PageBody extends Component{
constructor (props){
super(props)
this.state = {
is_crawling: false
}
this.crawlState = this.crawlState.bind(this)
}
crawlState (is_crawling) {
this.setState({is_crawling: is_crawling})
}
render () {
const show_modal = this.state.is_crawling;
return (
<div>
<Search crawlState={this.crawlState}/>
<Modal show_modal={show_modal}/>
</div>
)
}
}
search.js
import React, {Component} from 'react'
import request from 'superagent'
export default class Search extends Component{
constructor (props) {
super(props)
this.state = {
keyword: ''
,result: []
}
}
// method used to make ajax request
crawl = () => {
const keyword = this.state.keyword
this.props.crawlState(true) // set crawlstate as true to show modal
request // actual ajax request (superagent)
.get('/crawl')
.query({keyword: keyword})
.end((err, res) => {
if (err) console.log('superagent failed')
const r = res.body.result
this.setState({result: r})
this.props.crawlState(false) // set crawlstate as false to hide modal
})
}
onChangeHandler (e) {
this.setState({keyword: e.target.value})
}
render () {
const onChangeHandler = e => this.onChangeHandler(e)
const keyword = this.state.keyword
const arr = this.state.result.map((e, idx) => {
return <div key={idx}>{e}</div>
})
return (
<div>
<input type="text" onChange={onChangeHandler} value={keyword} />
<button onClick={this.crawl}>CRAWL</button>
{arr}
</div>
)
}
}
Hope this will help you.