6

में डेटा लोड हो रहा है मैं पूरी तरह से स्वीकार करता हूं कि मैं इस बिंदु पर प्रतिक्रियाशील मूल के लिए काफी नया हूं इसलिए मुझे उम्मीद है कि यह एक आसान उत्तर और संभावित बेवकूफ सवाल है :) असल में, यह हो सकता है आरएन मुद्दा प्रति से, जैसा कि मैं नीचे समझाऊंगा।एक प्रतिक्रियाशील मूल फ़्लैटलिस्ट

class MyScreen extends React.Component { 

    constructor(inProps) { 
    super(inProps); 
    this.state = { listData : [ ] }; 
    } 

    render() { return (
    <View> 
     <FlatList data={ this.state.listData } 
     renderItem={ ({item}) => 
      <Text>{item.firstName} {item.lastName}</Text> 
     } 
     /> 
    </View> 
); } 

    async componentDidMount() { 
    const data = [ ]; 
    let keys = await AsyncStorage.getAllKeys(); 
    keys.forEach(async function(inKey) { 
     let obj = await AsyncStorage.getItem(inKey); 
     obj = JSON.parse(obj); 
     data.push(obj); 
    }); 
    this.setState({ listData : data }); 
    }; 

} 

लक्ष्य AsyncStorage से डेटा लोड और इसे सूची में डंप करने के लिए है:

क्या मैं निम्नलिखित कोड है। काफी बुनियादी लगता है, है ना? दुर्भाग्य से, मैं इसे काम पर नहीं ला सकता: सूची खाली है।

अब बेवकूफ चीजों को कवर करने के लिए: हाँ, वास्तव में डेटा संग्रहीत किया गया है और हां, यह सही रूप में है (मुझे यह पता है क्योंकि अगर मैं केवल एक विशिष्ट वस्तु को पकड़ता हूं और इसे धक्का देता हूं) तो यह डेटा में दिखाई देता है अपेक्षित सूची)।

वास्तव में, मुझे पता है कि समस्या क्या है: यह है कि सेटस्टेट() कॉल कुंजी से पहले निष्पादित हो रही है .forEach() कॉल पूर्ण हो जाती है। मैं यह जानता हूँ क्योंकि अगर मैं setState() की जगह इस के साथ फोन:

setTimeout(function() { 
    this.setState({ listData : data }); 
}.bind(this), 1000); 

... फिर अचानक मेरी सूची में अपेक्षा के अनुरूप से भर जाता है (मैं भी कुछ console.log() के वहाँ में फेंक और देख सकते हैं कि चाबियों के बाद एक .forEach() कॉल वास्तव में कुंजी के अंदर उन लोगों के सामने निष्पादित करता है .for())। मुझे यह भी पता है कि स्पष्ट रूप से getItem() कॉल JSON.parse() से पहले प्रतीक्षा कर रहा है, अन्यथा यह बिल्कुल काम नहीं करेगा।

दूसरे शब्दों में: मुझे पता है कि यह इस कोड की असीमित प्रकृति के कारण होता है। मुझे यह समझने की प्रतीत नहीं होती है कि इससे बचने के लिए इसे सही तरीके से कैसे लिखना है।

मैं इसे देख रहा हूं और मैं सोच रहा हूं "ठीक है, कुंजी .forEach() एक अवरुद्ध कॉल है, तो यह सेटस्टेट() कॉल से पहले संभवतः कैसे पूरा नहीं हो सकता है, विशेष रूप से कुंजी पर एसिंक उपयोग दिया जाता है .forEach() कॉलबैक और getItem() अंदर कॉल का इंतजार है? "... केवल एक ही विचार था कि मैं चाबियों के सामने एक एसिंक ड्रॉप करना था। के लिए() कॉल करें, लेकिन इससे कोई फर्क नहीं पड़ता ।

तो, यह सार में एक मूल जावास्क्रिप्ट प्रश्न प्रतीत होता है, लेकिन मैं इसे हल नहीं कर सकता ... लेकिन दूसरी तरफ, मुझे यकीन नहीं है कि मैं इसे करने की कोशिश कर रहा हूं जिस तरह से मैं मूल रूप से आरएन भूमि में नहीं होना चाहिए और शायद यह असली समस्या है।

ध्यान दें कि अनुप्रयोग के माध्यम से प्रवाह (अन्य स्क्रीन पर जोड़े किए गए हैं) के कारण डेटा को एसिंक स्टोरेज से गतिशील रूप से खींचा जाना चाहिए, इसलिए ऐसा लगता है कि घटक में इसे लोड करने का प्रयास करना DidMount() समझ में आता है, मैं बस शामिल कॉल की असीमित प्रकृति के साथ लटका हो रही है।

कोई सुझाव?

धन्यवाद!

संपादित करें: मुझे यह भी जिक्र करना चाहिए कि मुझे यह पता होना चाहिए कि मैं इसे सुलझाने का एक तरीका जानता हूं कि केवल एसिंक्रोनस प्रकृति को पूरी तरह से हटा दें: व्यक्तिगत डेटा आइटम्स को संग्रहीत करने के बजाय, AsyncStorage में एक ही ऑब्जेक्ट में सबकुछ स्टोर करें। फिर मैं एक आइटम पढ़ सकता हूं, जो एक सरणी होगी (या एक सरणी होगी), तो केवल एसिंक्रोनस भाग getItem() कॉल है, लेकिन मैं इसके कॉलबैक संस्करण का उपयोग कर सकता हूं और इसे इस तरह से काम कर सकता हूं .. ।और मैं बिल्कुल कि दृष्टिकोण के खिलाफ नहीं हूँ, लेकिन इस बिंदु पर मैं वास्तव में समझने के लिए अगर कोई अन्य कारण से कुछ सीखने क्योंकि यह लगता है यह काम करना चाहिए की तरह :) क्या मैं गलत कर रहा हूँ चाहते

+0

एक सुपर:

for (let inKey of keys) { let obj = await AsyncStorage.getItem(inKey); obj = JSON.parse(obj); data.push(obj); } 

तुम सच में forEach चाहते हैं, आप अपने स्वयं के संस्करण है कि Promise रिटर्न लिखने के लिए ताकि आप उदाहरण के लिए उस पर await हुक कर सकते हैं हैकी रास्ता होगा ... {data.length> 1? this.setState ({listData: data}): emptylist} ... इसके अलावा, क्या आप data.push (obj) के ठीक बाद सेटस्टेट को ऊपर नहीं ले जा सकते हैं? यह अक्षम होगा, इस अर्थ में कि आप डेटा को फिर से लिख रहे हैं, लेकिन यह भी सुनिश्चित करेगा कि यदि आपको कोई त्रुटि आती है तो आपके पास डेटा है? Async Await मेरे लिए बहुत नया है, इसलिए इसे पोस्ट करने के लिए धन्यवाद। यह एक goooooooood प्रतिक्रिया सवाल है। –

उत्तर

3

keys.forEach कोड को अपने दायरे में (अपने स्वयं के कॉलबैक फ़ंक्शन में) निष्पादित करें, और यह आपके async/await जोड़ी को तोड़ देता है।

इस बजाय कार्य करें:

await keys.awaitableForEach(async function(inKey) { 
+0

सही दिखता है, धन्यवाद! मैं अंततः एक ऑब्जेक्ट दृष्टिकोण के साथ जाने जा रहा हूं क्योंकि यह वैसे भी अधिक कुशल है, लेकिन कम से कम अब मुझे समझ में आता है कि मुझे परेशानी क्यों हुई: मुझे एहसास नहीं हुआ कि प्रत्येक एसिंक/प्रतीक्षा जोड़ी को तोड़ देगा ... और वहां ' किसी भी विशिष्ट कारण के लिए मुझे उपयोग करने की आवश्यकता नहीं थी, केवल पहली बात थी जो दिमाग में आई थी। –

संबंधित मुद्दे