【问题标题】:undefined on getting specific value from State array - React Native从状态数组获取特定值时未定义 - React Native
【发布时间】:2019-12-05 12:29:50
【问题描述】:

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

当我

console.log(this.state.array)

它返回整个数组以及对象的所有数据,但是当 i

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

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

它返回未定义

.

我试图用

获取数据

forEach

循环,但似乎效果不佳。

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

    componentDidMount() {
        firebase.firestore().collection('pendingtips').get()
            .then(doc => { 
                doc.forEach(tip => { 
                    this.setState([...tips], 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”而不是未定义。

提前致谢。

【问题讨论】:

  • 你能在beakpoint分享这个阵列的打印屏幕吗?

标签: javascript arrays reactjs react-native


【解决方案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"));
  }

【讨论】:

  • 你能告诉我们你的渲染方法吗?不是renderTips
  • 将其更改为 ComponentDidMount 但主要问题是状态数组,this.state.array.push(object) 实际上对我有用。问题是我无法正确地从状态数组中获取数据
【解决方案2】:

我发现问题在于 JavaScript 将数组保存为对象。 例如这个数组:

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

等于:

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

"当你尝试访问索引 0 处的数组值时,你会得到 undefined,但这并不是 undefined 的值存储在索引 0 处,而是 JavaScript 中的默认行为是如果你尝试访问该值则返回 undefined不存在的键的对象。” as written in this article

【讨论】:

    【解决方案3】:

    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()}
    

    【讨论】:

    • 效果不佳...直接将我传给 .catch
    • 将其更改为 ComponentDidMount 但主要问题是状态数组,this.state.array.push(object) 实际上对我有用。问题是我无法正确地从状态数组中获取数据
    • 你可以这样做,{this.state.tips.length &gt; 0 &amp;&amp; this.renderTips()}
    • console.log(this.state.tips) 打印的是什么?
    • 同时尝试在您的 API 响应中打印 doc
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    相关资源
    最近更新 更多