react native - this.setState inside Promise cause strange behavior -
simplified issue. calling this.setstate inside promise, renders before ends pending promise.
my problems are:
- the this.setstate not immediatly returned
- i expected async, pending promise closed first.
- if break inside render function, catch inside promise called.
- maybe same issue 1) seems render still in context of promise in this.setstate called.
import dummydata_rankrequests "../dummydata/rankrequests"; class rankrequestlist extends component { constructor(props) { super(props); this.state = { loading: false, data: [], error: null }; this.makerankrequestcall = this.makerankrequestcall.bind(this); this.renderitem = this.renderitem.bind(this); } componentdidmount() { // works expected // console.log('start set'); // this.setstate({ data: dummydata_rankrequests.data, loading: false }); // console.log('end set'); this.makerankrequestcall() .then(done => { // never here console.log("done"); }); } makerankrequestcall() { console.log('call makerankrequestcall'); try { return new promise((resolve, reject) => { resolve(dummydata_rankrequests); }) .then(rankrequests => { console.log('start makerankrequestcall-rankrequests', rankrequests); this.setstate({ data: rankrequests.data, loading: false }); console.log('end _makerankrequestcall-rankrequests'); return null; }) .catch(error => { console.log('_makerankrequestcall-promisecatch', error); this.setstate({ error: rrerror.getrrerror(error), loading: false }); }); } catch (error) { console.log('_makerankrequestcall-catch', error); this.setstate({ error: rrerror.getrrerror(error), loading: false }); } } renderitem(data) { const height = 200; // force unknown named module error here return ( <view style={[styles.item, {height: height}]}> </view> ); } render() { let data = []; if (this.state.data && this.state.data.length > 0) { data = this.state.data.map(rr => { return object.assign({}, rr); }); } console.log('render-data', data); return ( <view style={styles.container}> <flatlist style={styles.listcontainer1} data={data} renderitem={this.renderitem} /> </view> ); } }
currrent logs shows:
- render-data, []
- start makerankrequestcall-rankrequests
- render-data, [...]
- _makerankrequestcall-promisecatch error: unknown named module...
- render-data, [...]
- possible unhandled promise
android emulator "react": "16.0.0-alpha.12", "react-native": "0.46.4",
edit: wrapping settimeout around this.setstate works
settimeout(() => { this.setstate({ data: respdata.data, loading: false }); }, 1000);
edit2: created bug report in react-native github in parallel https://github.com/facebook/react-native/issues/15214
both promise
, this.setstate()
asynchronous in javascript. say, if have following code:
console.log(a); networkrequest().then(result => console.log(result)); // networkrequest() promise console.log(b);
the , b printed first followed result of network request.
similarly, this.setstate()
asynchronous so, if want execute after this.setstate()
completed, need as:
this.setstate({data: rankrequests.data}, () => { // code needs run after changing state })
react re-renders every time this.setstate()
gets executed, hence getting component updated before whole promise gets resolved. problem can solved making componentdidmount()
async function , using await resolve promise:
async componentdidmount() { let rankrequests; try { rankrequests = await this.makerankrequestcall() // result contains data } catch(error) { console.error(error); } this.setstate({ data: rankrequests.data, loading: false }, () => { // need run after setting state }); }
hope helps.
Comments
Post a Comment