首页 > 解决方案 > 组件无法读取 JSON 属性

问题描述

我试图弄清楚为什么我的组件没有正确渲染。我正在尝试解析已保存到 redux 存储中的 JSON 文件,但每当我调用时,尝试通过诸如this.props.response.data.specificJSONObject. 相反,我会得到一个错误,指出cannot read property of 'specificJSONObject' of undefined. 这个问题一直困扰着我所有需要在 redux 存储中使用 JSON 文件的组件。我最初发现我的 redux 存储在进行分派时没有更新(问的问题:Redux state not being updated after dispatched actions)但已经修复了这个问题,现在我的 redux 存储能够存储它需要的获取数据但我仍然得到相同和以前一样的错误。

这是我的 Summary.js 屏幕,用于显示最少的可重现代码

import React, { Component } from "react";
import {
  View,
  ImageBackground,
  StyleSheet,
  Image,
  Text,
  FlatList
} from "react-native";
import { connect } from "react-redux";
import {
  fetchingSuccess,
  fetchingRequest,
  fetchingFailure,
  fetchData
} from "../data/redux/actions/appActions.js";
import PropTypes from "prop-types";
import LinkedName from "./LinkedName";
import ArticleBox from "./ArticleBox";

const styles = StyleSheet.create({
  container: {
    backgroundColor: "dimgrey",
    flex: 1
  },
  posLeft: {
    alignItems: "center",
    position: "absolute",
    top: 40,
    left: 25
  },
  posRight: {
    alignItems: "center",
    position: "absolute",
    top: 40,
    left: 175
  },
  text: {
    textAlign: "center",
    color: "#FFF"
  },
  header_text: {
    textAlign: "center",
    fontSize: 20,
    color: "#FFF"
  },
  image: {
    position: "absolute",
    top: 200,
    height: 375,
    width: 375,
    flex: 1
  },
  topPanel: {
    backgroundColor: "rgba(0.0,0.0,0.0,0.9)",
    height: 150,
    width: 300,
    position: "absolute",
    alignSelf: "center",
    flex: 2,
    flexDirection: "column",
    borderRadius: 25,
    borderWidth: 4
  },
  midPanel: {
    backgroundColor: "rgba(0.0,0.0,0.0,0.9)",
    height: 100,
    width: 300,
    position: "absolute",
    bottom: 120,
    alignSelf: "center",
    flex: 2,
    flexDirection: "column",
    borderRadius: 25,
    borderWidth: 4
  }
});

class Summary extends Component<Props> {
  constructor(props) {
    super(props);
    this.state = {
      taxonA: this.props.response.articles.taxon_a,
      taxonB: this.props.response.articles.taxon_b,
      sciNameA: this.props.response.articles.scientific_name_a,
      sciNameB: this.props.response.articles.scientific_name_b,
      hitRecords: Object.keys(this.props.response.articles.hit_records).map(
        key => ({ key, ...this.props.response.articles.hit_records[key] })
      ),
      TTOL:
        Math.round(this.props.response.articles.sum_simple_mol_time * 10) / 10,
      median: Math.round(this.props.response.articles.sum_median_time * 10) / 10
    };
    // console.log(STORE, this.props.response.articles);
  }
  componentDidMount = () => {
    console.log("STATE", this.state);
  };
  render() {
    return (
      <View style={styles.container}>
        <ImageBackground
          source={require("../assets/images/timescale.png")}
          style={styles.image}
          resizeMode="contain"
          alignSelf="center"
        >
          <View style={styles.topPanel}>
            <Text style={styles.header_text}>Query Taxa</Text>
            <View style={styles.posLeft}>
              <Text
                style={{ textAlign: "center", color: "#FFF", fontSize: 17 }}
              >
                Taxon A
              </Text>
              <Text />
              <Text style={styles.text}>{this.state.taxonA}</Text>
              <Text />
              <LinkedName
                url={this.state.hitRecords[0].link_taxon_a}
                latinName={this.state.sciNameA}
              />
            </View>
            <View style={styles.posRight}>
              <Text
                style={{ textAlign: "center", color: "#FFF", fontSize: 17 }}
              >
                Taxon B
              </Text>
              <Text />
              <Text style={styles.text}>{this.state.taxonB}</Text>
              <Text />
              <LinkedName
                url={this.state.hitRecords[0].link_taxon_b}
                latinName={this.state.sciNameB}
              />
            </View>
          </View>
          <View style={styles.midPanel}>
            <Text style={styles.header_text}>Result</Text>
            <Text />
            <Text style={styles.text}>TTOL: {this.state.TTOL} MYA</Text>
            <Text />
            <Text style={styles.text}>median: {this.state.median} MYA</Text>
          </View>
          <View style={{ position: "absolute", bottom: -35, marginLeft: -5 }}>
            <FlatList
              horizontal
              data={this.state.hitRecords}
              renderItem={({ item }) => {
                return (
                  <ArticleBox
                    title={item.title}
                    year={item.year}
                    time={item.time}
                    author={item.author}
                  />
                );
              }}
              itemSeparatorComponent={() => (
                <View
                  style={{
                    backgroundColor: "#ff8c00",
                    height: 100,
                    width: 100
                  }}
                />
              )}
            />
          </View>
        </ImageBackground>
      </View>
    );
  }
}

Summary.propTypes = {
  fetchData: PropTypes.func.isRequired,
  response: PropTypes.object.isRequired
};

const mapStateToProps = state => {
  return { response: state };
};

const mapStateToDispatch = dispatch => ({
  fetchData: url => dispatch(fetchData(url))
});

export default connect(
  mapStateToProps,
  mapStateToDispatch
)(Summary);

这是我通过 props 引用 Redux 状态的函数

constructor(props) {
    super(props);
    this.state = {
      taxonA: this.props.response.articles.taxon_a,
      taxonB: this.props.response.articles.taxon_b,
      sciNameA: this.props.response.articles.scientific_name_a,
      sciNameB: this.props.response.articles.scientific_name_b,
      hitRecords: Object.keys(this.props.response.articles.hit_records).map(
        key => ({ key, ...this.props.response.articles.hit_records[key] })
      ),
      TTOL:
        Math.round(this.props.response.articles.sum_simple_mol_time * 10) / 10,
      median: Math.round(this.props.response.articles.sum_median_time * 10) / 10
    };
    // console.log(STORE, this.props.response.articles);
  }

在这个实例中,我在构建状态时就构建了它,但在其他组件中,我将通过componentWillMount函数设置状态,问题仍然存在。

我的预期输出应该没有错误,并且我的组件可以正确呈现。收到的输出是红屏会的错误信息cannot read property of 'specificJSONObject' of undefined

标签: react-native

解决方案


上面链接的问题中的答案有助于解决这个问题,但也会在这里解释。

在我的摘要屏幕中,问题被映射到响应。如果你看到MapStatetoProps函数是这样写的

const mapStateToProps = state => {
  return { response: state };
};

但应该这样写

const mapStateToProps = state => {
      return { response: state.fetchingStatus };
};

由于我的 Redux 商店的设置和调度方式(可以在上面链接的问题中看到)


推荐阅读