React - My component is not updating the state after a promise












0















I'm just a beguinner in React-Native and i'm getting crazy every day with somo unexpected behaviors. Of course it is my fault, I'm still learning.
Today i'm struggling to understand whats is goin on with my code.



I have a function that call an array of objects on my local storage. If I console the response from the promise it gives me a perfect array (i think). After that I setState and agin it appears correctly on my console. But, for my surprise, my list component doesn't render anything (and it's surely working as it was before).



I'll put my code attached:






/*FUNCTION FILE*/

getAllData: async () => {
var data = [{id:null, address:null, name:null}];
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (err, stores) => {
stores.map((result, i, store) => {
// get at each store's key/value so you can work with it
var key = store[i][0];
var value = store[i][1];
data[i] = {id: i, address: key, name: value}
});
});
});
return data},








//MAIN FILE (DAD COMPONENT)


import React, { Component } from 'react';
import { View, Text } from 'react-native';

import NewTagButton from '../components/NewTagButton';



import TagList from '../components/TagList';
import storage from '../functions/Storage';
import { Object } from 'core-js';
//import { TagPosition } from '../functions/GPSTag'

class TagsScreen extends Component {
constructor(props) {
super(props);

this.state = {message:"",
pairedDevices: ,

};
}

componentDidMount () {
var self = this;
storage.getAllData() //tem que esperar a promise
.then(function (devices) {
self.setState({message: "Scaneamento finalizado."});
self.setState({pairedDevices: devices});

console.log("devices")
console.log(devices)
console.log("State")
console.log(self.state.pairedDevices)
})
.catch(()=> console.log("Promise rejected"))
}



render() {

return (
<View>
<Text>{this.state.message}</Text>
<TagList devices = {this.state.pairedDevices} origem = 'MyTag'/>
<NewTagButton/>
</View>
);
}
}

export default TagsScreen;








LIST COMPONENT THAT SHOULD RENDER THE LIST

import React from 'react';
import { View, StyleSheet } from 'react-native';

import TagItem from '../components/TagItem'


const TagList = props => {

const devicesList = props.devices;
const origem = props.origem;

//aqui a gente vai passar device a device para a page TagItem
const items = devicesList.map((device) =>

<TagItem
key = {device.address}
address = {device.address}
name = {device.name}
origem = {origem}/>
);


return (
<View key = {items} styles = {styles.container}>
{items}
</View>
);
}



const styles = StyleSheet.create({
container : {
alignItems:'center',


}
})

export default TagList;





Thank you.



EDIT:
I've put some logs between the components, the image is on a url because I don't have enough reputation haha



Console.Log



EDIT2:



I just created a silly button to set a state just with a string. After this state changing, the app render the list. For sure is a promise problem, can someone help me? =]










share|improve this question

























  • I think you need to change key = {items} to something else so that it will re-render.

    – Colin
    Nov 27 '18 at 23:16











  • Could you place some logs inside the taglist function to see if the function gets executed? Then it will be easier to isolate where the issue is.

    – Viktor W
    Nov 27 '18 at 23:22











  • Colin, i've tried to change the key but nothing happens. Actually, this component is utilized in one more place and it's working. I think the problem lays on object handling, maybe i'm make a confusion with Object indexes...

    – Matheus Molin
    Nov 27 '18 at 23:35
















0















I'm just a beguinner in React-Native and i'm getting crazy every day with somo unexpected behaviors. Of course it is my fault, I'm still learning.
Today i'm struggling to understand whats is goin on with my code.



I have a function that call an array of objects on my local storage. If I console the response from the promise it gives me a perfect array (i think). After that I setState and agin it appears correctly on my console. But, for my surprise, my list component doesn't render anything (and it's surely working as it was before).



I'll put my code attached:






/*FUNCTION FILE*/

getAllData: async () => {
var data = [{id:null, address:null, name:null}];
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (err, stores) => {
stores.map((result, i, store) => {
// get at each store's key/value so you can work with it
var key = store[i][0];
var value = store[i][1];
data[i] = {id: i, address: key, name: value}
});
});
});
return data},








//MAIN FILE (DAD COMPONENT)


import React, { Component } from 'react';
import { View, Text } from 'react-native';

import NewTagButton from '../components/NewTagButton';



import TagList from '../components/TagList';
import storage from '../functions/Storage';
import { Object } from 'core-js';
//import { TagPosition } from '../functions/GPSTag'

class TagsScreen extends Component {
constructor(props) {
super(props);

this.state = {message:"",
pairedDevices: ,

};
}

componentDidMount () {
var self = this;
storage.getAllData() //tem que esperar a promise
.then(function (devices) {
self.setState({message: "Scaneamento finalizado."});
self.setState({pairedDevices: devices});

console.log("devices")
console.log(devices)
console.log("State")
console.log(self.state.pairedDevices)
})
.catch(()=> console.log("Promise rejected"))
}



render() {

return (
<View>
<Text>{this.state.message}</Text>
<TagList devices = {this.state.pairedDevices} origem = 'MyTag'/>
<NewTagButton/>
</View>
);
}
}

export default TagsScreen;








LIST COMPONENT THAT SHOULD RENDER THE LIST

import React from 'react';
import { View, StyleSheet } from 'react-native';

import TagItem from '../components/TagItem'


const TagList = props => {

const devicesList = props.devices;
const origem = props.origem;

//aqui a gente vai passar device a device para a page TagItem
const items = devicesList.map((device) =>

<TagItem
key = {device.address}
address = {device.address}
name = {device.name}
origem = {origem}/>
);


return (
<View key = {items} styles = {styles.container}>
{items}
</View>
);
}



const styles = StyleSheet.create({
container : {
alignItems:'center',


}
})

export default TagList;





Thank you.



EDIT:
I've put some logs between the components, the image is on a url because I don't have enough reputation haha



Console.Log



EDIT2:



I just created a silly button to set a state just with a string. After this state changing, the app render the list. For sure is a promise problem, can someone help me? =]










share|improve this question

























  • I think you need to change key = {items} to something else so that it will re-render.

    – Colin
    Nov 27 '18 at 23:16











  • Could you place some logs inside the taglist function to see if the function gets executed? Then it will be easier to isolate where the issue is.

    – Viktor W
    Nov 27 '18 at 23:22











  • Colin, i've tried to change the key but nothing happens. Actually, this component is utilized in one more place and it's working. I think the problem lays on object handling, maybe i'm make a confusion with Object indexes...

    – Matheus Molin
    Nov 27 '18 at 23:35














0












0








0








I'm just a beguinner in React-Native and i'm getting crazy every day with somo unexpected behaviors. Of course it is my fault, I'm still learning.
Today i'm struggling to understand whats is goin on with my code.



I have a function that call an array of objects on my local storage. If I console the response from the promise it gives me a perfect array (i think). After that I setState and agin it appears correctly on my console. But, for my surprise, my list component doesn't render anything (and it's surely working as it was before).



I'll put my code attached:






/*FUNCTION FILE*/

getAllData: async () => {
var data = [{id:null, address:null, name:null}];
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (err, stores) => {
stores.map((result, i, store) => {
// get at each store's key/value so you can work with it
var key = store[i][0];
var value = store[i][1];
data[i] = {id: i, address: key, name: value}
});
});
});
return data},








//MAIN FILE (DAD COMPONENT)


import React, { Component } from 'react';
import { View, Text } from 'react-native';

import NewTagButton from '../components/NewTagButton';



import TagList from '../components/TagList';
import storage from '../functions/Storage';
import { Object } from 'core-js';
//import { TagPosition } from '../functions/GPSTag'

class TagsScreen extends Component {
constructor(props) {
super(props);

this.state = {message:"",
pairedDevices: ,

};
}

componentDidMount () {
var self = this;
storage.getAllData() //tem que esperar a promise
.then(function (devices) {
self.setState({message: "Scaneamento finalizado."});
self.setState({pairedDevices: devices});

console.log("devices")
console.log(devices)
console.log("State")
console.log(self.state.pairedDevices)
})
.catch(()=> console.log("Promise rejected"))
}



render() {

return (
<View>
<Text>{this.state.message}</Text>
<TagList devices = {this.state.pairedDevices} origem = 'MyTag'/>
<NewTagButton/>
</View>
);
}
}

export default TagsScreen;








LIST COMPONENT THAT SHOULD RENDER THE LIST

import React from 'react';
import { View, StyleSheet } from 'react-native';

import TagItem from '../components/TagItem'


const TagList = props => {

const devicesList = props.devices;
const origem = props.origem;

//aqui a gente vai passar device a device para a page TagItem
const items = devicesList.map((device) =>

<TagItem
key = {device.address}
address = {device.address}
name = {device.name}
origem = {origem}/>
);


return (
<View key = {items} styles = {styles.container}>
{items}
</View>
);
}



const styles = StyleSheet.create({
container : {
alignItems:'center',


}
})

export default TagList;





Thank you.



EDIT:
I've put some logs between the components, the image is on a url because I don't have enough reputation haha



Console.Log



EDIT2:



I just created a silly button to set a state just with a string. After this state changing, the app render the list. For sure is a promise problem, can someone help me? =]










share|improve this question
















I'm just a beguinner in React-Native and i'm getting crazy every day with somo unexpected behaviors. Of course it is my fault, I'm still learning.
Today i'm struggling to understand whats is goin on with my code.



I have a function that call an array of objects on my local storage. If I console the response from the promise it gives me a perfect array (i think). After that I setState and agin it appears correctly on my console. But, for my surprise, my list component doesn't render anything (and it's surely working as it was before).



I'll put my code attached:






/*FUNCTION FILE*/

getAllData: async () => {
var data = [{id:null, address:null, name:null}];
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (err, stores) => {
stores.map((result, i, store) => {
// get at each store's key/value so you can work with it
var key = store[i][0];
var value = store[i][1];
data[i] = {id: i, address: key, name: value}
});
});
});
return data},








//MAIN FILE (DAD COMPONENT)


import React, { Component } from 'react';
import { View, Text } from 'react-native';

import NewTagButton from '../components/NewTagButton';



import TagList from '../components/TagList';
import storage from '../functions/Storage';
import { Object } from 'core-js';
//import { TagPosition } from '../functions/GPSTag'

class TagsScreen extends Component {
constructor(props) {
super(props);

this.state = {message:"",
pairedDevices: ,

};
}

componentDidMount () {
var self = this;
storage.getAllData() //tem que esperar a promise
.then(function (devices) {
self.setState({message: "Scaneamento finalizado."});
self.setState({pairedDevices: devices});

console.log("devices")
console.log(devices)
console.log("State")
console.log(self.state.pairedDevices)
})
.catch(()=> console.log("Promise rejected"))
}



render() {

return (
<View>
<Text>{this.state.message}</Text>
<TagList devices = {this.state.pairedDevices} origem = 'MyTag'/>
<NewTagButton/>
</View>
);
}
}

export default TagsScreen;








LIST COMPONENT THAT SHOULD RENDER THE LIST

import React from 'react';
import { View, StyleSheet } from 'react-native';

import TagItem from '../components/TagItem'


const TagList = props => {

const devicesList = props.devices;
const origem = props.origem;

//aqui a gente vai passar device a device para a page TagItem
const items = devicesList.map((device) =>

<TagItem
key = {device.address}
address = {device.address}
name = {device.name}
origem = {origem}/>
);


return (
<View key = {items} styles = {styles.container}>
{items}
</View>
);
}



const styles = StyleSheet.create({
container : {
alignItems:'center',


}
})

export default TagList;





Thank you.



EDIT:
I've put some logs between the components, the image is on a url because I don't have enough reputation haha



Console.Log



EDIT2:



I just created a silly button to set a state just with a string. After this state changing, the app render the list. For sure is a promise problem, can someone help me? =]






/*FUNCTION FILE*/

getAllData: async () => {
var data = [{id:null, address:null, name:null}];
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (err, stores) => {
stores.map((result, i, store) => {
// get at each store's key/value so you can work with it
var key = store[i][0];
var value = store[i][1];
data[i] = {id: i, address: key, name: value}
});
});
});
return data},





/*FUNCTION FILE*/

getAllData: async () => {
var data = [{id:null, address:null, name:null}];
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (err, stores) => {
stores.map((result, i, store) => {
// get at each store's key/value so you can work with it
var key = store[i][0];
var value = store[i][1];
data[i] = {id: i, address: key, name: value}
});
});
});
return data},





//MAIN FILE (DAD COMPONENT)


import React, { Component } from 'react';
import { View, Text } from 'react-native';

import NewTagButton from '../components/NewTagButton';



import TagList from '../components/TagList';
import storage from '../functions/Storage';
import { Object } from 'core-js';
//import { TagPosition } from '../functions/GPSTag'

class TagsScreen extends Component {
constructor(props) {
super(props);

this.state = {message:"",
pairedDevices: ,

};
}

componentDidMount () {
var self = this;
storage.getAllData() //tem que esperar a promise
.then(function (devices) {
self.setState({message: "Scaneamento finalizado."});
self.setState({pairedDevices: devices});

console.log("devices")
console.log(devices)
console.log("State")
console.log(self.state.pairedDevices)
})
.catch(()=> console.log("Promise rejected"))
}



render() {

return (
<View>
<Text>{this.state.message}</Text>
<TagList devices = {this.state.pairedDevices} origem = 'MyTag'/>
<NewTagButton/>
</View>
);
}
}

export default TagsScreen;





//MAIN FILE (DAD COMPONENT)


import React, { Component } from 'react';
import { View, Text } from 'react-native';

import NewTagButton from '../components/NewTagButton';



import TagList from '../components/TagList';
import storage from '../functions/Storage';
import { Object } from 'core-js';
//import { TagPosition } from '../functions/GPSTag'

class TagsScreen extends Component {
constructor(props) {
super(props);

this.state = {message:"",
pairedDevices: ,

};
}

componentDidMount () {
var self = this;
storage.getAllData() //tem que esperar a promise
.then(function (devices) {
self.setState({message: "Scaneamento finalizado."});
self.setState({pairedDevices: devices});

console.log("devices")
console.log(devices)
console.log("State")
console.log(self.state.pairedDevices)
})
.catch(()=> console.log("Promise rejected"))
}



render() {

return (
<View>
<Text>{this.state.message}</Text>
<TagList devices = {this.state.pairedDevices} origem = 'MyTag'/>
<NewTagButton/>
</View>
);
}
}

export default TagsScreen;





LIST COMPONENT THAT SHOULD RENDER THE LIST

import React from 'react';
import { View, StyleSheet } from 'react-native';

import TagItem from '../components/TagItem'


const TagList = props => {

const devicesList = props.devices;
const origem = props.origem;

//aqui a gente vai passar device a device para a page TagItem
const items = devicesList.map((device) =>

<TagItem
key = {device.address}
address = {device.address}
name = {device.name}
origem = {origem}/>
);


return (
<View key = {items} styles = {styles.container}>
{items}
</View>
);
}



const styles = StyleSheet.create({
container : {
alignItems:'center',


}
})

export default TagList;





LIST COMPONENT THAT SHOULD RENDER THE LIST

import React from 'react';
import { View, StyleSheet } from 'react-native';

import TagItem from '../components/TagItem'


const TagList = props => {

const devicesList = props.devices;
const origem = props.origem;

//aqui a gente vai passar device a device para a page TagItem
const items = devicesList.map((device) =>

<TagItem
key = {device.address}
address = {device.address}
name = {device.name}
origem = {origem}/>
);


return (
<View key = {items} styles = {styles.container}>
{items}
</View>
);
}



const styles = StyleSheet.create({
container : {
alignItems:'center',


}
})

export default TagList;






reactjs react-native promise es6-promise react-props






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 28 '18 at 2:13







Matheus Molin

















asked Nov 27 '18 at 23:13









Matheus MolinMatheus Molin

11




11













  • I think you need to change key = {items} to something else so that it will re-render.

    – Colin
    Nov 27 '18 at 23:16











  • Could you place some logs inside the taglist function to see if the function gets executed? Then it will be easier to isolate where the issue is.

    – Viktor W
    Nov 27 '18 at 23:22











  • Colin, i've tried to change the key but nothing happens. Actually, this component is utilized in one more place and it's working. I think the problem lays on object handling, maybe i'm make a confusion with Object indexes...

    – Matheus Molin
    Nov 27 '18 at 23:35



















  • I think you need to change key = {items} to something else so that it will re-render.

    – Colin
    Nov 27 '18 at 23:16











  • Could you place some logs inside the taglist function to see if the function gets executed? Then it will be easier to isolate where the issue is.

    – Viktor W
    Nov 27 '18 at 23:22











  • Colin, i've tried to change the key but nothing happens. Actually, this component is utilized in one more place and it's working. I think the problem lays on object handling, maybe i'm make a confusion with Object indexes...

    – Matheus Molin
    Nov 27 '18 at 23:35

















I think you need to change key = {items} to something else so that it will re-render.

– Colin
Nov 27 '18 at 23:16





I think you need to change key = {items} to something else so that it will re-render.

– Colin
Nov 27 '18 at 23:16













Could you place some logs inside the taglist function to see if the function gets executed? Then it will be easier to isolate where the issue is.

– Viktor W
Nov 27 '18 at 23:22





Could you place some logs inside the taglist function to see if the function gets executed? Then it will be easier to isolate where the issue is.

– Viktor W
Nov 27 '18 at 23:22













Colin, i've tried to change the key but nothing happens. Actually, this component is utilized in one more place and it's working. I think the problem lays on object handling, maybe i'm make a confusion with Object indexes...

– Matheus Molin
Nov 27 '18 at 23:35





Colin, i've tried to change the key but nothing happens. Actually, this component is utilized in one more place and it's working. I think the problem lays on object handling, maybe i'm make a confusion with Object indexes...

– Matheus Molin
Nov 27 '18 at 23:35












2 Answers
2






active

oldest

votes


















1














Solution



The getAllKeys and multiGet of AsyncStorage are return promise. You need to use await for returning data is applied data from your logic.



getAllData = async () => {
var data = [{id:null, address:null, name:null}];
await AsyncStorage.getAllKeys(async (err, keys) => { // This is async function.
await AsyncStorage.multiGet(keys, (err, stores) => { // This is async function also.
stores.map((result, i, store) => {
// get at each store's key/value so you can work with it
var key = store[i][0];
var value = store[i][1];
data[i] = {id: i, address: key, name: value}
});
});
});
console.log(data); // Check your data.
return data
}


Why?



It will return data before finishing Promise function's promise without concern.
Check the process number by order below.



getAllData = async () => {
var data = [{id:null, address:null, name:null}]; // 1.

AsyncStorage.getAllKeys((err, keys) => { // 4. there is no async await decoration
AsyncStorage.multiGet(keys, (err, stores) => { // 3. there is no async await decoration
stores.map((result, i, store) => {
// get at each store's key/value so you can work with it
var key = store[i][0];
var value = store[i][1];
data[i] = {id: i, address: key, name: value}
});
});
});

return data // 2.
}


Thus, data has null when return from the getAllData function. After that, AsyncStorage's functions will be applied to the data variable.






share|improve this answer


























  • I agree with you that is something about the promises, but I can't call "await" there. It pop's a error saying its not a sync function... (wtf)

    – Matheus Molin
    Nov 28 '18 at 8:11











  • DId you check the decoration async in front of getAllKeys's callback?

    – Jeff Gu Kang
    Nov 29 '18 at 8:12





















0














I've looked through your code a while and came up with a few things. Essentially, you're code isn't perfect, but I don't see anything that would break it like you are experiencing. Likely the issue is outside where you are looking. Either where TagsScreen is being called, or TagItem. Your edit with the console log isn't very clear where they are being called from as your example code hasn't been updated.



A couple of notes which may help you get on your way.




  • You can console log objects with console.log('myMessage', myObject); Unless you use JSON.stringify(), you're going to get [Object object] if you try to add an object to a string.

  • In your Promise.then, you don't want to call self.setState twice. This will render the app twice. You can see that in your console.log. Both of those can be in one setState; one object.

  • Calling your console.logs immediately after you set the state will make it look like the state isn't being updated. setState is async and will be fired after the event queue is cleared. If you want to track when the state has changed, use the react lifecycle function componentDidUpdate(oldProps){}

  • It would be helpful if you paired down your code so it can be run in jsFiddle. This is as far as I got, but it works perfectly. I have included lots of comments which explain what is exactly happening.


Steps I would take to debug:




  1. Add a console.log on deviceList inside TagList to ensure it is being called and the data is there.

  2. Ensure items is an array of TagItem jsx objects.

  3. Verify that the TagList html is being added to the DOM.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53509666%2freact-my-component-is-not-updating-the-state-after-a-promise%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    Solution



    The getAllKeys and multiGet of AsyncStorage are return promise. You need to use await for returning data is applied data from your logic.



    getAllData = async () => {
    var data = [{id:null, address:null, name:null}];
    await AsyncStorage.getAllKeys(async (err, keys) => { // This is async function.
    await AsyncStorage.multiGet(keys, (err, stores) => { // This is async function also.
    stores.map((result, i, store) => {
    // get at each store's key/value so you can work with it
    var key = store[i][0];
    var value = store[i][1];
    data[i] = {id: i, address: key, name: value}
    });
    });
    });
    console.log(data); // Check your data.
    return data
    }


    Why?



    It will return data before finishing Promise function's promise without concern.
    Check the process number by order below.



    getAllData = async () => {
    var data = [{id:null, address:null, name:null}]; // 1.

    AsyncStorage.getAllKeys((err, keys) => { // 4. there is no async await decoration
    AsyncStorage.multiGet(keys, (err, stores) => { // 3. there is no async await decoration
    stores.map((result, i, store) => {
    // get at each store's key/value so you can work with it
    var key = store[i][0];
    var value = store[i][1];
    data[i] = {id: i, address: key, name: value}
    });
    });
    });

    return data // 2.
    }


    Thus, data has null when return from the getAllData function. After that, AsyncStorage's functions will be applied to the data variable.






    share|improve this answer


























    • I agree with you that is something about the promises, but I can't call "await" there. It pop's a error saying its not a sync function... (wtf)

      – Matheus Molin
      Nov 28 '18 at 8:11











    • DId you check the decoration async in front of getAllKeys's callback?

      – Jeff Gu Kang
      Nov 29 '18 at 8:12


















    1














    Solution



    The getAllKeys and multiGet of AsyncStorage are return promise. You need to use await for returning data is applied data from your logic.



    getAllData = async () => {
    var data = [{id:null, address:null, name:null}];
    await AsyncStorage.getAllKeys(async (err, keys) => { // This is async function.
    await AsyncStorage.multiGet(keys, (err, stores) => { // This is async function also.
    stores.map((result, i, store) => {
    // get at each store's key/value so you can work with it
    var key = store[i][0];
    var value = store[i][1];
    data[i] = {id: i, address: key, name: value}
    });
    });
    });
    console.log(data); // Check your data.
    return data
    }


    Why?



    It will return data before finishing Promise function's promise without concern.
    Check the process number by order below.



    getAllData = async () => {
    var data = [{id:null, address:null, name:null}]; // 1.

    AsyncStorage.getAllKeys((err, keys) => { // 4. there is no async await decoration
    AsyncStorage.multiGet(keys, (err, stores) => { // 3. there is no async await decoration
    stores.map((result, i, store) => {
    // get at each store's key/value so you can work with it
    var key = store[i][0];
    var value = store[i][1];
    data[i] = {id: i, address: key, name: value}
    });
    });
    });

    return data // 2.
    }


    Thus, data has null when return from the getAllData function. After that, AsyncStorage's functions will be applied to the data variable.






    share|improve this answer


























    • I agree with you that is something about the promises, but I can't call "await" there. It pop's a error saying its not a sync function... (wtf)

      – Matheus Molin
      Nov 28 '18 at 8:11











    • DId you check the decoration async in front of getAllKeys's callback?

      – Jeff Gu Kang
      Nov 29 '18 at 8:12
















    1












    1








    1







    Solution



    The getAllKeys and multiGet of AsyncStorage are return promise. You need to use await for returning data is applied data from your logic.



    getAllData = async () => {
    var data = [{id:null, address:null, name:null}];
    await AsyncStorage.getAllKeys(async (err, keys) => { // This is async function.
    await AsyncStorage.multiGet(keys, (err, stores) => { // This is async function also.
    stores.map((result, i, store) => {
    // get at each store's key/value so you can work with it
    var key = store[i][0];
    var value = store[i][1];
    data[i] = {id: i, address: key, name: value}
    });
    });
    });
    console.log(data); // Check your data.
    return data
    }


    Why?



    It will return data before finishing Promise function's promise without concern.
    Check the process number by order below.



    getAllData = async () => {
    var data = [{id:null, address:null, name:null}]; // 1.

    AsyncStorage.getAllKeys((err, keys) => { // 4. there is no async await decoration
    AsyncStorage.multiGet(keys, (err, stores) => { // 3. there is no async await decoration
    stores.map((result, i, store) => {
    // get at each store's key/value so you can work with it
    var key = store[i][0];
    var value = store[i][1];
    data[i] = {id: i, address: key, name: value}
    });
    });
    });

    return data // 2.
    }


    Thus, data has null when return from the getAllData function. After that, AsyncStorage's functions will be applied to the data variable.






    share|improve this answer















    Solution



    The getAllKeys and multiGet of AsyncStorage are return promise. You need to use await for returning data is applied data from your logic.



    getAllData = async () => {
    var data = [{id:null, address:null, name:null}];
    await AsyncStorage.getAllKeys(async (err, keys) => { // This is async function.
    await AsyncStorage.multiGet(keys, (err, stores) => { // This is async function also.
    stores.map((result, i, store) => {
    // get at each store's key/value so you can work with it
    var key = store[i][0];
    var value = store[i][1];
    data[i] = {id: i, address: key, name: value}
    });
    });
    });
    console.log(data); // Check your data.
    return data
    }


    Why?



    It will return data before finishing Promise function's promise without concern.
    Check the process number by order below.



    getAllData = async () => {
    var data = [{id:null, address:null, name:null}]; // 1.

    AsyncStorage.getAllKeys((err, keys) => { // 4. there is no async await decoration
    AsyncStorage.multiGet(keys, (err, stores) => { // 3. there is no async await decoration
    stores.map((result, i, store) => {
    // get at each store's key/value so you can work with it
    var key = store[i][0];
    var value = store[i][1];
    data[i] = {id: i, address: key, name: value}
    });
    });
    });

    return data // 2.
    }


    Thus, data has null when return from the getAllData function. After that, AsyncStorage's functions will be applied to the data variable.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 29 '18 at 8:12

























    answered Nov 28 '18 at 5:17









    Jeff Gu KangJeff Gu Kang

    1,7491723




    1,7491723













    • I agree with you that is something about the promises, but I can't call "await" there. It pop's a error saying its not a sync function... (wtf)

      – Matheus Molin
      Nov 28 '18 at 8:11











    • DId you check the decoration async in front of getAllKeys's callback?

      – Jeff Gu Kang
      Nov 29 '18 at 8:12





















    • I agree with you that is something about the promises, but I can't call "await" there. It pop's a error saying its not a sync function... (wtf)

      – Matheus Molin
      Nov 28 '18 at 8:11











    • DId you check the decoration async in front of getAllKeys's callback?

      – Jeff Gu Kang
      Nov 29 '18 at 8:12



















    I agree with you that is something about the promises, but I can't call "await" there. It pop's a error saying its not a sync function... (wtf)

    – Matheus Molin
    Nov 28 '18 at 8:11





    I agree with you that is something about the promises, but I can't call "await" there. It pop's a error saying its not a sync function... (wtf)

    – Matheus Molin
    Nov 28 '18 at 8:11













    DId you check the decoration async in front of getAllKeys's callback?

    – Jeff Gu Kang
    Nov 29 '18 at 8:12







    DId you check the decoration async in front of getAllKeys's callback?

    – Jeff Gu Kang
    Nov 29 '18 at 8:12















    0














    I've looked through your code a while and came up with a few things. Essentially, you're code isn't perfect, but I don't see anything that would break it like you are experiencing. Likely the issue is outside where you are looking. Either where TagsScreen is being called, or TagItem. Your edit with the console log isn't very clear where they are being called from as your example code hasn't been updated.



    A couple of notes which may help you get on your way.




    • You can console log objects with console.log('myMessage', myObject); Unless you use JSON.stringify(), you're going to get [Object object] if you try to add an object to a string.

    • In your Promise.then, you don't want to call self.setState twice. This will render the app twice. You can see that in your console.log. Both of those can be in one setState; one object.

    • Calling your console.logs immediately after you set the state will make it look like the state isn't being updated. setState is async and will be fired after the event queue is cleared. If you want to track when the state has changed, use the react lifecycle function componentDidUpdate(oldProps){}

    • It would be helpful if you paired down your code so it can be run in jsFiddle. This is as far as I got, but it works perfectly. I have included lots of comments which explain what is exactly happening.


    Steps I would take to debug:




    1. Add a console.log on deviceList inside TagList to ensure it is being called and the data is there.

    2. Ensure items is an array of TagItem jsx objects.

    3. Verify that the TagList html is being added to the DOM.






    share|improve this answer




























      0














      I've looked through your code a while and came up with a few things. Essentially, you're code isn't perfect, but I don't see anything that would break it like you are experiencing. Likely the issue is outside where you are looking. Either where TagsScreen is being called, or TagItem. Your edit with the console log isn't very clear where they are being called from as your example code hasn't been updated.



      A couple of notes which may help you get on your way.




      • You can console log objects with console.log('myMessage', myObject); Unless you use JSON.stringify(), you're going to get [Object object] if you try to add an object to a string.

      • In your Promise.then, you don't want to call self.setState twice. This will render the app twice. You can see that in your console.log. Both of those can be in one setState; one object.

      • Calling your console.logs immediately after you set the state will make it look like the state isn't being updated. setState is async and will be fired after the event queue is cleared. If you want to track when the state has changed, use the react lifecycle function componentDidUpdate(oldProps){}

      • It would be helpful if you paired down your code so it can be run in jsFiddle. This is as far as I got, but it works perfectly. I have included lots of comments which explain what is exactly happening.


      Steps I would take to debug:




      1. Add a console.log on deviceList inside TagList to ensure it is being called and the data is there.

      2. Ensure items is an array of TagItem jsx objects.

      3. Verify that the TagList html is being added to the DOM.






      share|improve this answer


























        0












        0








        0







        I've looked through your code a while and came up with a few things. Essentially, you're code isn't perfect, but I don't see anything that would break it like you are experiencing. Likely the issue is outside where you are looking. Either where TagsScreen is being called, or TagItem. Your edit with the console log isn't very clear where they are being called from as your example code hasn't been updated.



        A couple of notes which may help you get on your way.




        • You can console log objects with console.log('myMessage', myObject); Unless you use JSON.stringify(), you're going to get [Object object] if you try to add an object to a string.

        • In your Promise.then, you don't want to call self.setState twice. This will render the app twice. You can see that in your console.log. Both of those can be in one setState; one object.

        • Calling your console.logs immediately after you set the state will make it look like the state isn't being updated. setState is async and will be fired after the event queue is cleared. If you want to track when the state has changed, use the react lifecycle function componentDidUpdate(oldProps){}

        • It would be helpful if you paired down your code so it can be run in jsFiddle. This is as far as I got, but it works perfectly. I have included lots of comments which explain what is exactly happening.


        Steps I would take to debug:




        1. Add a console.log on deviceList inside TagList to ensure it is being called and the data is there.

        2. Ensure items is an array of TagItem jsx objects.

        3. Verify that the TagList html is being added to the DOM.






        share|improve this answer













        I've looked through your code a while and came up with a few things. Essentially, you're code isn't perfect, but I don't see anything that would break it like you are experiencing. Likely the issue is outside where you are looking. Either where TagsScreen is being called, or TagItem. Your edit with the console log isn't very clear where they are being called from as your example code hasn't been updated.



        A couple of notes which may help you get on your way.




        • You can console log objects with console.log('myMessage', myObject); Unless you use JSON.stringify(), you're going to get [Object object] if you try to add an object to a string.

        • In your Promise.then, you don't want to call self.setState twice. This will render the app twice. You can see that in your console.log. Both of those can be in one setState; one object.

        • Calling your console.logs immediately after you set the state will make it look like the state isn't being updated. setState is async and will be fired after the event queue is cleared. If you want to track when the state has changed, use the react lifecycle function componentDidUpdate(oldProps){}

        • It would be helpful if you paired down your code so it can be run in jsFiddle. This is as far as I got, but it works perfectly. I have included lots of comments which explain what is exactly happening.


        Steps I would take to debug:




        1. Add a console.log on deviceList inside TagList to ensure it is being called and the data is there.

        2. Ensure items is an array of TagItem jsx objects.

        3. Verify that the TagList html is being added to the DOM.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 28 '18 at 5:07









        NathanNathan

        37113




        37113






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53509666%2freact-my-component-is-not-updating-the-state-after-a-promise%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

            Calculate evaluation metrics using cross_val_predict sklearn

            Insert data from modal to MySQL (multiple modal on website)