Как отобразить данные в ScrollView React Native (expo cli) из базы данных firebase в реальном времени?

#javascript #reactjs #firebase #react-native #expo

# #javascript #reactjs #firebase #реагировать-родной #expo

Вопрос:

Я работаю над приложением ToDo, которое подключено к базе данных Firebase в реальном времени. Все работает нормально. Я также могу хранить данные в базе данных Firebase, но проблема в том, что я не могу получить какие-либо данные из базы данных. Я хочу отображать данные в ScrollView, чтобы данные могли отображаться в ScrollView при открытии моего приложения.

Main.js

     import React, { Component } from 'react';
    import {
        StyleSheet,
        Text,
        View,
        TextInput,
        ScrollView,
        TouchableOpacity
    } from 'react-native';
    
    import Note from './Note';
    import firebase from './firebase';
    
    export default class Main extends React.Component {
    
        constructor(props) {
            super(props);
    
            this.state = {
                noteArray: [],
                noteText: ''
            }
    
        }
    
        render() {

 let notes = () => {
    firebase.database().ref(`todos`).on('value', function (snapshot) {
      return <Note key={snapshot.val().key} keyval={snapshot.val().key} val={snapshot.val().note}
                    deleteMethod={() => this.deleteNote(key)}
                />
    });
  }
    
           
            return (
                <View style={styles.container}>
                    <View style={styles.header}>
                        <Text style={styles.headerText}>Todo</Text>
                    </View>
    
                    <ScrollView style={styles.scrollContainer}>
                        {notes}
                    </ScrollView>
    
                    <View style={styles.footer}>
                        <TextInput
                            style={styles.textInput}
                            onChangeText={(noteText) => this.setState({ noteText })}
                            value={this.state.noteText}
                            placeholder='Enter Task'
                            placeholderTextColor='white'
                            underlineColorAndroid='transparent'>
                        </TextInput>
                    </View>
    
    
                    <TouchableOpacity onPress={this.adTask.bind(this)} style={styles.addButton}>
                        <Text style={styles.addButtonText}>Add</Text>
    
                    </TouchableOpacity>
    
                </View>
    
            );
        }
    
        adTask() {
            if (this.state.noteText) {
                var date = new Date();
    
                var database = firebase.database().ref('todos');
                var key = database.push().key;
    
                var todo = {
                    'date': date.getDay()  
                        '/'   (date.getMonth()   1)  
                        '/'   date.getFullYear(),
                    'note': this.state.noteText,
                    key: key
                }
                database.child(key).set(todo);
    
                this.setState({ noteArray: this.state.noteArray });
                this.setState({ noteText: this.state.noteText });
                this.setState({
                    noteText: this.state.noteText = ""
                })
            }
        }
 

note.js

      import React from 'react';
    import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
    import { AntDesign } from '@expo/vector-icons';
    
    export default class Main extends React.Component {
    
        render() {
            return (
                <View key={this.props.keyval} style={styles.note}>
                    <Text style={styles.noteText}>{this.props.val.note}</Text>
                    <Text style={styles.noteDate}>{this.props.val.date}</Text>
    
                    <TouchableOpacity onPress={this.props.deleteMethod} style={styles.noteDelete}>
                        <Text style={styles.noteDeleteText}><AntDesign name="delete" size={24} color="black" /></Text>
                    </TouchableOpacity>
    
                </View>
    
            );
        }
    }
 

Ответ №1:

Вы удалили переменную состояния noteArray, но вы ее вообще не используете. В идеале вы должны настроить прослушиватель изменений данных realtime database и обновлять свое локальное состояние при изменении данных. Вы можете настроить функцию прослушивания и вызвать ее внутри вашего Main.js componentDidMount метода жизненного цикла файла.

Внутри этой функции вы можете обновить свое локальное состояние noteArray значением, полученным из базы данных в реальном времени. Затем вы можете отобразить noteArray для отображения ваших заметок в вашем приложении с помощью scrollview. Я бы лично посоветовал вам использовать FlatList реализацию react native в этом случае, поскольку этот массив заметок может расти со временем. Это поможет вам избежать проблем с производительностью, с которыми вы можете столкнуться в случае длинного списка и scrollview.

Main.js

 import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  TextInput,
  ScrollView,
  TouchableOpacity,
  FlatList
} from 'react-native';
import Note from './Note';
import firebase from './firebase';

export default class Main extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      noteArray: [],
      noteText: ''
    }
  }

  componentDidMount() {
    this.listenForNotes()
  }

  listenForNotes() {
    firebase.database().ref(`todos`).on('value', function (snapshot) {
      const notes = [];
      snapshot.forEach(child => {
        notes.push({
          note: child.val().name,
          date: child.val().date,
          key: child.key
        });
      });
      this.setState({
        noteArray: notes
      });
    });
  }

  adTask() {
    if (this.state.noteText) {
      var date = new Date();
      var database = firebase.database().ref('todos');
      var key = database.push().key;
      var todo = {
        'date': date.getDay()  
          '/'   (date.getMonth()   1)  
          '/'   date.getFullYear(),
        'note': this.state.noteText,
        key: key
      }
      database.child(key).set(todo);
      this.setState({ noteText: "" });
    }
  }

  deleteNote(key) {
    // your delete note function
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.header}>
          <Text style={styles.headerText}>Todo</Text>
        </View>
        <FlatList
          data={noteArray}
          renderItem={({ item, index }) => {
            return (
              <Note
                key={item.key}
                note={item.note}
                date={item.date}
                deleteMethod={() => this.deleteNote(key)}
              />
            );
          }}
          key={(item) => `${item.key}`}
        />
        <View style={styles.footer}>
          <TextInput
            style={styles.textInput}
            onChangeText={(noteText) => this.setState({ noteText })}
            value={this.state.noteText}
            placeholder='Enter Task'
            placeholderTextColor='white'
            underlineColorAndroid='transparent'>
          </TextInput>
        </View>
        <TouchableOpacity onPress={this.adTask.bind(this)} style={styles.addButton}>
          <Text style={styles.addButtonText}>Add</Text>
        </TouchableOpacity>
      </View>
    );
  }
}
 

Вы также должны внести некоторые изменения в Note.js файл, чтобы отобразить переданные реквизиты.

Note.js

 import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { AntDesign } from '@expo/vector-icons';

export default class Note extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    const { note, date, key, deleteMethod } = this.props;
    return (
      <View key={key} style={styles.note}>
        <Text style={styles.noteText}>{note}</Text>
        <Text style={styles.noteDate}>{date}</Text>
        <TouchableOpacity onPress={deleteMethod} style={styles.noteDelete}>
          <Text style={styles.noteDeleteText}><AntDesign name="delete" size={24} color="black" /></Text>
        </TouchableOpacity>
      </View>
    );
  }
}
 

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

1. Я получаю ошибку в компоненте FlatList, которая выглядит так: ReferenceError: noteArray не определен <FlatList data={noteArray} когда я меняю его на data={this.state.noteArray}, это выдает другую ошибку: TypeError: не удается прочитать свойство ‘setState’ null: this.setState({noteArray: примечания });

2. что мне теперь делать?

3. Я загрузил весь свой код здесь для тестирования, пожалуйста, проверьте: codesandbox.io/s/stupefied-snowflake-1lddp?file=/src/App.js