Интеграция базы данных Firebase в реальном времени с приложением React Native

#javascript #react-native #firebase-realtime-database

# #javascript #react-native #firebase-realtime-database

Вопрос:

Я впервые узнаю о состоянии и следую простому руководству по созданию приложения react native. В руководстве не рассматривалось использование firebase, так что это то, что я собрал вместе. Он «работает», но не извлекает данные базы данных при первом рендеринге. Я знаю, что это из-за задержки во времени, необходимой для сбора данных и рендеринга моего приложения. Но я не знаю, как мне переместить логику, чтобы исправить это. Я чувствую, что должен использовать .тогда как-то? Или я делаю все это совершенно неправильно…

 import {db} from '../../src/config.js';

let initialMessages = [];
db.ref().once('value', (snapshot) =>{
  snapshot.forEach((child)=>{
    child.forEach(function(childChildSnapshot) {
      initialMessages.push({
        id: childChildSnapshot.key,
        title: childChildSnapshot.val().title,
      })
    })
  })
})
.then()
.catch((error) => {console.error('Error:', error)});

function MessagesScreen(props) {
  const [messages, setMessages] = useState(initialMessages);
  return (
    <Screens>
      <View style={styles.wholeThing}>
         <FlatList
          data={messages}
          keyExtractor={(messages) => messages.id.toString()}
          renderItem={({ item }) => (
            <Card
              title={item.title}
              onPress={() => console.log("hi")}
            />
          )}
          ItemSeparatorComponent={ListItemSeparator}
          contentContainerStyle={styles.messagesList}
          refreshing={refreshing}
          onRefresh={}
        />
      </View>
    </Screens>
  );
}

export default MessagesScreen;
 

Ответ №1:

К тому времени, когда вы переходите initialMessages к перехвату состояния (в качестве его начального значения), initialMessages.push(...) он еще не был вызван.

Вместо этого вам нужно вызвать setMessages , когда данные загружены:

 db.ref().once('value', (snapshot) =>{
  snapshot.forEach((child)=>{
    child.forEach(function(childChildSnapshot) {
      initialMessages.push({
        id: childChildSnapshot.key,
        title: childChildSnapshot.val().title,
      })
    })
    setMessages(initialMessages);
  })
})
 

setMessages Затем вызов приведет к повторному отображению (затронутого) Пользовательский интерфейс, и это покажет сообщения.

Это, конечно, означает, что вам нужно вытащить useState хук из MessagesScreen , чтобы он также был виден в том месте, где вы сейчас вызываете setMessages .

Комментарии:

1. Большое вам спасибо, это имеет смысл. Моя проблема сейчас в том, что когда я вытащил хук useState, он говорит мне, что он должен быть в функциональном компоненте. Означает ли это, что мне нужно каким-то образом поместить мою логику db.ref() в свой собственный компонент?

2. Я давно не создавал функциональные компоненты, поэтому рекомендую поискать новое сообщение об ошибке. Но мое первое предположение — переместить загрузку данных в function MessagesScreen(props) { функции и / или, возможно, в useEffect хук.