【问题标题】:Update selected item from Flatlist in Firebase using React Native使用 React Native 从 Firebase 中的 Flatlist 更新所选项目
【发布时间】:2017-10-20 00:55:43
【问题描述】:

我需要为 Flatlist 中选择的项目更新 Firebase 中的“状态”字段。选择项目时,会出现一个弹出窗口,用户可以选择“完成?”或“失败?”。当代码运行“goalComplete”和“goalFailed”函数时会发生错误,因为 Firebase 引用无法连接到正确的路径。 'onRenderItem' 函数在 'item.key' 上打印正确的键。

错误是“无法读取未定义的'key'的属性”,当'goalComplete'或'goalFailed'运行时发生。

'goal' 和 'status' 字段是使用 .push 函数放入 Firebase 的,该函数会生成我试图在 Firebase 路径中引用的密钥,每一个都比“goal”和“status”高一级项目。

非常感谢您的帮助。

import React, { Component } from 'react';
import { Text, FlatList, View, Image, TouchableOpacity, Alert } from 'react-native';
import firebase from 'firebase';
import { Button, Card, CardSection } from '../common';
import styles from '../Styles';

class List extends Component {

    static navigationOptions = {
        title: 'List',
    }

    constructor(props) {
        super(props);

        this.state = {
            goallist: '',
            loading: false,
    };
  }

componentDidMount() {
    this.setState({ loading: true });
    const { currentUser } = firebase.auth();
    const keyParent = firebase.database().ref(`/users/${currentUser.uid}/goalProfile`);
    keyParent.on(('child_added'), snapshot => {
      const newChild = {
           key: snapshot.key,
           goal: snapshot.val().goal,
           status: snapshot.val().status
        };
        this.setState((prevState) => ({ goallist: [...prevState.goallist, newChild] }));
        console.log(this.state.goallist);
        });

this.setState({ loading: false });
}

onRenderItem = ({ item }) => (
    <TouchableOpacity onPress={this.showAlert}>
        <Text style={styles.listStyle}>
             { item.goal } { item.key }
        </Text>
    </TouchableOpacity>
);

goalComplete = ({ item }) => {
    const { currentUser } = firebase.auth();

 firebase.database().ref(`/users/${currentUser.uid}/goalProfile/${item.key}`).update({
        status: 'Done'
    });//this is not updating status in Firebase for the item selected (get 'key is undefined)'
}

goalFailed = ({ item }) => {
    const { currentUser } = firebase.auth();
    firebase.database().ref(`/users/${currentUser.uid}/goalProfile/${item.key}`).update({
        status: 'Fail'
    });//this is not updating status in Firebase for the item selected (get 'key is undefined)'
}

showAlert = () => {
    Alert.alert(
        'Did you succeed or fail?',
        'Update your status',
   [
        { text: 'Completed?',
            onPress: this.goalComplete
        },
        { text: 'Failed?',
            onPress: this.goalFailed
        },
        { text: 'Cancel',
            onPress: () => console.log('Cancel Pressed'),
            style: 'cancel' },
   ],
       { cancelable: false }
   );
}

keyExtractor = (item) => item.key;

render() {
  return (
    <Card>

      <View style={{ flex: 1 }}>
       <FlatList
          data={this.state.goallist}
          keyExtractor={this.keyExtractor}
          extraData={this.state}
          renderItem={this.onRenderItem}
        />
      </View>

    </Card>
    );
  }
}

export { List };

【问题讨论】:

    标签: javascript firebase react-native firebase-realtime-database


    【解决方案1】:

    您没有将item 传递给您的任何函数调用,因此它将参数解释为未定义,因此是您的问题。您需要通过逻辑传递项目,以便可以访问正确的 firebase 路径。您也可以使用 state 变量,但这是另一回事

    位置 1

    onRenderItem = (item) => (
    <TouchableOpacity onPress={() => {this.showAlert(item)}}>
    ...
    

    位置 2

    showAlert = (item) => {
    Alert.alert(...
    

    位置 3

    { text: 'Completed?',
            onPress: () => this.goalComplete(item)
        },
        { text: 'Failed?',
            onPress: () => this.goalFailed(item)
        },
    

    另请注意,您的方法的参数不需要包含在 {}

    编辑:您的 TouchableOpacity 不需要在括号中包含项目,所以它现在看起来像这样:&lt;TouchableOpacity onPress={() =&gt; {this.showAlert(item)}}&gt;

    在位置 3,您需要做同样的事情。您需要将引用传递给您要调用的函数onPress,您当前的执行方式会立即调用它。

    【讨论】:

    • 感谢您的回复。在 IDE Atom 或位置 1 上,对于“onPress={(item)...”,我得到“项目已在上层范围内声明”。它还想要一个 ;在 this.showAlert(item) 之后。然后,当我运行它时,我不断收到“超出最大调用堆栈大小”。你知道如何解决这个问题吗?
    • 我进行了更改,但我这样做了:。警报弹出窗口被激活,没有任何被按下,goalComplete 和goalFailed 函数也交替触发,没有被按下。这就是最终导致“超出最大堆栈大小”的原因。它正在 Firebase 中找到正确的路径,并在“完成”和“失败”之间反复更改所有 Flatlist 项目的状态,无需用户交互。请帮忙。
    • 使用您的代码,您在渲染时调用该函数,而不是将函数传递给 onPress。我已经编辑了我的答案(“编辑”之后的详细信息)以正确执行此操作。您必须使用 onPress = {() =&gt; function()} 以使其不会立即触发。
    • 你可以找到类似的问题/来源here
    • 谢谢。我得到了你的解决方案,eslint 标记了一些语法差异。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-24
    • 2018-03-23
    • 1970-01-01
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多