从状态数组获取特定值时未定义-React Native

时间:2019-07-27 12:46:37

标签: javascript arrays reactjs react-native

我正在从firestore中读取数据,并将其存储在对象的状态数组中。

当我

console.log(this.state.array)

它返回带有对象所有数据的整个数组,但是当我

console.log(this.state.array.name)

console.log(this.state.array[0])

  

返回未定义

我尝试使用

获取数据

forEach

循环,但似乎效果不佳。

    constructor(props) {
        super(props);
        this.state = { tips: [] };
    }

    componentWillMount() {
        firebase.firestore().collection('pendingtips').get()
            .then(doc => { 
                doc.forEach(tip => { 
                    this.state.tips.push(tip.data()); 
                    console.log(this.state.tips);
                }); 
            })
            .catch(() => Alert.alert('error'));
    }

    renderTips() {
        console.log(this.state.tips); //returns the whole array as expected
        console.log(this.state.tips[0].name); //returns undefined
        return this.state.tips.map(tip => <PendingTip key={tip.tip} name={tip.name} tip={tip.tip} />); //return null because tip is undefined
    } 
   render() {
        return (
            <View style={styles.containerStyle}>
                <ScrollView style={styles.tipsContainerStyle}>
                    {this.renderTips()}
                </ScrollView>
            </View>
        );
    }

数组结构为:

"tips": [
    { name: "X", tip: "Y" },
    { name: "Z", tip: "T" }
]

所以我希望this.state.tips [0] .name为“ X”而不是未定义。

提前谢谢。

3 个答案:

答案 0 :(得分:1)

  1. 首先,您应该在componentDidMount中而不是componentWillMount中获取数据。

https://reactjs.org/docs/faq-ajax.html#where-in-the-component-lifecycle-should-i-make-an-ajax-call

  1. 第二,您应该使用this.setState来更新状态,而不是直接对其进行突变。
  componentDidMount() {
    firebase
      .firestore()
      .collection("pendingtips")
      .get()
      .then(docs => {
        const tips = docs.map(doc => doc.data());

        this.setState({ tips });
      })
      .catch(() => Alert.alert("error"));
  }

答案 1 :(得分:0)

firesore请求是async,因此,当您的请求得到执行时,组件将被挂载,结果控制台中的状态将变得不确定。

您必须在componentDidMount而不是componentWillMount中进行API调用。

这样的更改/更改状态将不会触发组件的重新渲染,并且您的组件将无法获取最新数据,

doc.forEach(tip => { 
      this.state.tips.push(tip.data()); 
      console.log(this.state.tips);
}); 

您必须使用setState来更改状态,这样做将重新呈现组件,并且您一直在获取最新数据。

componentDidMount(){
  firebase.firestore().collection('pendingtips').get()
     .then(doc => { 
         const tipsData = doc.map(tip => tip.data());
         this.setState({tips:tipsData},() => console.log(this.state.tips));
     })
     .catch(() => Alert.alert('error'));
}

在调用renderTips函数时,请确保您的状态数组中有数据,

{this.state.tips.length > 0 && this.renderTips()}

答案 2 :(得分:0)

我发现问题在于JavaScript将数组另存为对象。 例如此数组:

[ 'a' , 'b' , 'c' ]

等于:

{
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
}

“当您尝试访问索引0处的数组值时,您会得到未定义的信息,但这不是未定义值存储在索引0处,这是JavaScript的默认行为是,如果您尝试访问该值,则返回undefined对于不存在的密钥的对象。” as written in this article