Reputation: 67
When the user clicks a button, I want the app to
The problem I'm seeing is that pulling down all rows doesn't include the one that was just posted unless I include a manual delay (via setTimeout).
This is what my 2 functions look like
// gets all data, updates state, thus triggering react to rerender
listWords() {
setTimeout(() => fetch("http://localhost:9000/listWords")
.then(res => res.text())
.then(res => this.setState({ wordList: JSON.parse(res)})), 2000)
}
// sends new word to the MySQL database, then kicks off the listWords process to refetch all data
addWord() {
fetch("http://localhost:9000/addWord", {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
word: this.state.newWord
})
})
.then(res => res.json())
.then(this.listWords())
}
I shouldn't have to have that setTimeout in there, but when I remove it, the listWords update doesn't have the newly posted row.
My best guess is that either
.then()
paradigm, orHow can I ensure the POST has successfully completed before I pull the rows again?
I am using react, express, sequelize, and for the DB it's MySQL in a docker container.
Upvotes: 2
Views: 1006
Reputation: 4544
You indeed made a mistake, a common trap which I myself fell into as well a few times :)
When calling addWord()
it will evaluate then(this.listWords())
. This will immediately call listWords()
.
Instead you pass a function to then(...)
(instead of calling a function) for example like this:
.then(() => this.listWords())
or even like this:
.then(this.listWords)
Now, instead of passing the result of listWords()
to then()
it will pass a function that will call listWords()
to then()
thus only executing listWords()
when the Promise reaches this then()
Example to make this behavior even clearer:
When calling a function function foo(arg1) {}
, JS needs to know the value of arg1
before calling foo
. Let's take the following piece of code:
foo(bar())
In this case, bar()
must be called before foo(...)
because the arg1
will be the returned value of bar()
. In constrast to the following case:
foo(() => bar())
Now, arg1
will be a function instead of the returned value of bar()
. This is equivalent to:
var arg = () => bar();
foo(arg);
In contrast to:
var arg = bar();
foo(arg);
Where it is obvious what will happen.
In chained functions like foo(arg1).bar(arg2).baz(arg3)
, all args will be evaluated before calling foo(...)
.
Some help to debug such problems: Use the Network Inspector in your browser. It will show the order of requests performed and in this example you would have seen that the GET
request was actually performed before the POST
request. This might not explain why it happens but you can understand the problem faster.
Upvotes: 2