Trying to implement a SIMPLE promise in Reactjs
Solution 1
You are using React
in a wrong way. A Promise
is designed to return result at a later point of time. By the time your promise has been resolved
or rejected
, your render
would have finished execution and it wont update when the promise completes.
render
method should only depend on props
and/or state
to render the desired output. Any change to prop
or state
would re-render
your component.
- First, identify where your
Promise
should go in the life cycle of the component(here) -
In your case i would do the following
-
Initialize an state inside your constructor(ES6) or via
getInitialState
constructor(props) { super(props); this.state = { name: '', }; }
-
Then on
componentWillMount
orcomponentDidMount
which ever suits you, call the promise therecomponentWillMount() { var promise = new Promise( (resolve, reject) => { let name = 'Paul' if (name === 'Paul') { resolve("Promise resolved successfully"); } else { reject(Error("Promise rejected")); } }); let obj = {newName: ''}; promise.then( result => { this.setState({name: result}); }, function(error) { this.setState({name: error}); }); }
-
Then in
render
method write something similar to this.render() { return ( <div className="App"> <h1>Hello World</h1> <h2>{this.state.name}</h2> </div> ); }
-
Solution 2
You need to be thinking about the scope you're in. When you are in the function you're passing to promise.then
, you are in a new block scope and therefore any var you create in the function won't exist outside of it's scope. I'm not sure how you're defining your React components, but assuming you have a newName
variable on your component, there are two ways you could solve the scope problem - bind and arrow functions:
promise.then(function(result) {
this.newName = result; //or what you want to assign it to
}.bind(this))
and then you could reference it using {this.newName}
Or with an arrow function:
promise.then((result) => {
this.newName = result; //or what you want to assign it to
}.bind(this))
I would recommend watching this egghead video to help you understand the this
keyword in javascript.
Paulos3000
Keen Angular developer, interested in finding new and better ways of building stylish, but clean and efficient SPA's.
Updated on August 01, 2022Comments
-
Paulos3000 almost 2 years
Just trying out Promises for the first time in React. I have a basic promise working (ripped from someone else's code), but don't know how to adapt it to be useful.
What I have so far (within my
render()
function)var promise = new Promise( (resolve, reject) => { let name = 'Dave' if (name === 'Dave') { resolve("Promise resolved successfully"); } else { reject(Error("Promise rejected")); } }); promise.then(function(result) { console.log(result); // "Promise resolved successfully" }, err => { console.log(err); // Error: "Promise rejected" });
Sure enough, as the promise conditional is matched (
name === 'Dave'
), my console logsPromise resolved successfully
.However, I don't know how to assign a value to a variable when using the promise. For example:
promise.then(function(result) { var newName = 'Bob' }, function(err) { var newName = 'Anonymous' });
And then when I try to return this value in
render()
's return statement, like so:<h2>{newName}</h2>
It says newName is undefined.
I have also tried:
promise.then(function(result) { var newName = result }, function(err) { var newName = error });
...expecting this would assign the
resolve
orerror
string intonewName
variable, but nope.Am I thinking about this the wrong way? How can I make this more useful than just logging a string when my conditional is met?
Any help would be appreciated, because this is really making my head hurt...
Update
render() { var promise = new Promise( (resolve, reject) => { let name = 'Paul' if (name === 'Paul') { resolve("Promise resolved successfully"); } else { reject(Error("Promise rejected")); } }); let obj = {newName: ''}; promise.then( result => { obj["newName"] = result }, function(error) { obj["newName"] = error }); console.log(obj.newName) return ( <div className="App"> <h1>Hello World</h1> <h2>{obj.newName}</h2> </div> ); }
-
Paulos3000 over 7 yearsThat worked! I actually tried that before but it didn't return the correct state value, not sure why. Maybe a typo/syntax error... Anyway, thanks!