首页 > 解决方案 > 反应状态数组索引不可能

问题描述

我有一个反应组件:

export default class Detail extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: null,
      description: null,
      address: null,
      coordinates: null
    };
  }
  componentDidMount() {
    const apiUrl = `http://localhost:8000/api/frontend/listing/${
      this.props.match.params.id
    }`;
    fetch(apiUrl)
      .then(response => response.json())
      .then(response =>
        this.setState({
          name: response.name,
          description: response.description,
          address: response.address,
          coordinates: response.coordinates
        })
      );
  }

  render() {
    return (
      <div>
        <MapComponent
          isMarkerShown
          googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places"
          loadingElement={<div style={{ height: `100%` }} />}
          containerElement={<div style={{ height: `400px` }} />}
          mapElement={<div style={{ height: `100%` }} />}
          coords={this.state.coordinates}
          />
      </div>
    );
  }
}

它使用以下组件:

const MapComponent = withScriptjs(
  withGoogleMap(props => (
    <GoogleMap
      defaultZoom={8}
      defaultCenter={{ lat: +props.coords[0], lng: +props.coords[1] }}
    >
      {props.isMarkerShown && (
        <Marker position={{ lat: +props.coords[0], lng: +props.coords[1] }} />
      )}
    </GoogleMap>
  ))
);

这无法编译,错误是

无法读取 null 的属性“0”

当它试图索引坐标数组时。为了调试它,我尝试删除索引(即 lat 和 lng 都等于 props.coords)。显然,这在逻辑上是没有意义的,Google API 抱怨了,但 react 没有。此外,使用 chrome react 工具显示 props.coords 确实存在,并且是一个包含预期的两个坐标的数组。那么为什么 javascript 不让我索引一个数组呢?

标签: javascriptreactjsstatereact-props

解决方案


问题不在于数组,问题在于您的数据是异步获取的。在MapComponent获取数据之前呈现。

在 React 中处理这些情况的一种常见做法是检查渲染方法中的状态,并在获取数据时渲染微调器或“请稍候”消息等。

当数据可用并使用该数据设置状态时,组件将再次自动呈现,这次显示数据。

例子:

export default class Detail extends Component {
    constructor(props) {
        super(props);
        this.state = {
            name: null,
            description: null,
            address: null,
            coordinates: null
        };
    }
    componentDidMount() {
        const apiUrl = `http://localhost:8000/api/frontend/listing/${
            this.props.match.params.id
            }`;
        fetch(apiUrl)
            .then(response => response.json())
            .then(response =>
                this.setState({
                    name: response.name,
                    description: response.description,
                    address: response.address,
                    coordinates: response.coordinates
                })
            );
    }

    render() {
        if (!this.state.coordinates) {
            return <div>Fetching data, please wait…&lt;/div>;
        }
        return (
            <div>
                <MapComponent
                    isMarkerShown
                    googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places"
                    loadingElement={<div style={{ height: `100%` }} />}
                    containerElement={<div style={{ height: `400px` }} />}
                    mapElement={<div style={{ height: `100%` }} />}
                    coords={this.state.coordinates}
                />
            </div>
        );
    }
}

推荐阅读