【问题标题】:Unable to access state from render return call - 'Cannot read property 'instructionList' of null'无法从渲染返回调用访问状态 - '无法读取属性'instructionList' of null'
【发布时间】:2019-08-04 09:42:32
【问题描述】:

我正在自学 React,同时从事一个项目,该项目使用 react-google-maps 包生成从 A 到 B 方向的地图。地图本身工作正常,但我现在尝试打印相应的路线方向html 通过 return 方法,但无法将这些说明打印出来。

根据我通过 Google 和 StackOverflow 进行的研究,我认为我的问题可能是:

  1. 尝试在返回方法中访问我的instructionList 时的“this”关键字的范围。在这种情况下 - 我需要输入什么来访问我的 instructionList 数组 <li> 项目? 我也试过 <ol>{DirectionsService.route.state.instructionList}</ol><ol> and {DirectionsComponent.DirectionsService.route.state.instructionList}</ol> 也不起作用

  2. 加载页面时,不一定收到api响应,因此我的instructionList为空,无法呈现。在哪种情况下 - 应该如何处理?

  3. 我在语法中不知道的其他内容(我是 react 的初学者,而且 react-google-maps 包!)

在我的代码中,我在 state 中定义了一个名为指令列表的数组,其中包含从 A 到 B 的指令

if (status === google.maps.DirectionsStatus.OK) {
  this.setState({
    directions: { ...result },
    markers: true
  });
  this.setState({
    instructions: this.state.directions.routes[0].legs[0].steps
  });
  this.setState({
    instructionList: this.state.instructions.map(instruction => {
      return <li>instruction.instructions</li>;
    })
  });
}

然后我尝试在类返回方法中访问此数组 - 但错误消息显示 instructionList 未定义。

return (
  <div>
      <DirectionsComponent/>
      <div className="route instructions">
        <h1>{title}</h1>
        <ol>{this.state.instructionList}</ol>
      </div>
      <NotificationContainer />
  </div>

下面是一段更完整的代码,如果这样更容易识别问题。

class MyMapComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    const {
      startLat,
      startLng,
      finishLat,
      finishLng,
      transportMode,
      title
    } = this.props;

    const DirectionsComponent = compose(
      withProps({
        googleMapURL:
          "https://maps.googleapis.com/maps/api/js?key=APIKEYGOESHERE", //removed=&callback=initMap
        loadingElement: <div style={{ height: `400px` }} />,
        containerElement: <div style={{ width: `100%` }} />,
        mapElement: <div style={{ height: `400px`, width: `400px` }} />
      }),
      withScriptjs,
      withGoogleMap,
      lifecycle({
        componentDidMount() {
          const DirectionsService = new google.maps.DirectionsService();

          DirectionsService.route(
            {
              origin: new google.maps.LatLng(startLat, startLng),
              destination: new google.maps.LatLng(finishLat, finishLng),
              travelMode: google.maps.TravelMode[transportMode],
              provideRouteAlternatives: true
            },
            (result, status) => {
              if (status === google.maps.DirectionsStatus.OK) {
                this.setState({
                  directions: { ...result },
                  markers: true
                });
                this.setState({
                  instructions: this.state.directions.routes[0].legs[0].steps
                });
                this.setState({
                  instructionList: this.state.instructions.map(instruction => {
                    return <li>instruction.instructions</li>;
                  })
                });
              } else {
                console.error(
                  `There was an error fetching directions for the specified journey ${result}`
                );
                NotificationManager.error(
                  "Journey cannot be retrieved, please try again",
                  "Error",
                  20000
                );
              }
            }
          );
        }
      })
    )(props => (
      <GoogleMap defaultZoom={3}>
        {props.directions && (
          <DirectionsRenderer
            directions={props.directions}
            suppressMarkers={props.markers}
          />
        )}
      </GoogleMap>
    ));
    return (
      <div>
        <DirectionsComponent />
        <div className="route instructions">
          <h1>{title}</h1>
          <ol>{this.state.instructionList}</ol>
        </div>
        <NotificationContainer />
      </div>
    );
  }
}
export default MyMapComponent;

错误信息当前为TypeError: Cannot read property 'instructionList' of null

我已经玩过代码并进行了相当多的研究,但我正在兜圈子。我确定解决方案很快,但由于我对 React/react-google-maps 的了解有限,我很难找到它,所以我非常感谢任何能够提供帮助的人:)

【问题讨论】:

    标签: javascript reactjs react-google-maps


    【解决方案1】:

    您还没有初始化组件的state。所以你不能访问state 的属性。您需要在constructor 中初始化它。

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

    更新

    您需要定义onChangeInstructionList 以在DirectionsComponent 中更改MyMapComponentinstructionList。您还需要将DirectionsComponent 移动到MyMapComponentcomponentDidMount,以避免由于状态更改而导致无限循环。

    class MyMapComponent {
      constructor(props){
        super(props);
        this.state = {
          instructionList: [],
        };
    
        this.onChangeInstructionList = this.onChangeInstructionList.bind(this);
      }
    
      componentDidMount() {
        const {startLat, startLng, finishLat, finishLng, transportMode} = this.props;
        const DirectionsComponent = compose(
          withProps({
            googleMapURL: "https://maps.googleapis.com/maps/api/js?key=APIKEYGOESHERE",//removed=&callback=initMap
            loadingElement: <div style={{ height: `400px` }} />,
            containerElement: <div style={{ width: `100%` }} />,
            mapElement: <div style={{height: `400px`, width: `400px` }}  />,
            onChangeInstructionList: this.onChangeInstructionList,
          }),
          withScriptjs,
          withGoogleMap,
          lifecycle({
            componentDidMount() {
              const DirectionsService = new google.maps.DirectionsService();
    
              DirectionsService.route({
                origin: new google.maps.LatLng(startLat, startLng),
                destination: new google.maps.LatLng(finishLat, finishLng),
                travelMode: google.maps.TravelMode[transportMode],
                provideRouteAlternatives: true
              }, (result, status) => {
    
                if (status === google.maps.DirectionsStatus.OK) {
                  this.setState({
                    directions: {...result},
                    markers: true
                  })
                  this.setState({instructions: this.state.directions.routes[0].legs[0].steps});
                  this.props.onChangeInstructionList(this.state.instructions.map(instruction => {
                    return (<li>instruction.instructions</li>);
                  }));
                } else {
                  console.error(`There was an error fetching directions for the specified journey ${result}`);
                  NotificationManager.error("Journey cannot be retrieved, please try again", "Error", 20000);
                }
              });
            }
          })
        )(props =>
          <GoogleMap
            defaultZoom={3}
          >
            {props.directions && <DirectionsRenderer directions={props.directions} suppressMarkers={props.markers}/>}
          </GoogleMap>
        );
    
        this.setState({
          DirectionsComponent,
        })
      }
    
      onChangeInstructionList(newList) {
        this.setState({
          instructionList: newList,
        });
      }
    
      render() {
        const {title} = this.props;
        const { DirectionsComponent, instructionList } = this.state;
        return (
          <div>
            <DirectionsComponent/>
            <div className="route instructions">
              <h1>{title}</h1>
              <ol>{instructionList}</ol>
            </div>
            <NotificationContainer />
          </div>
    
        )
      }
    }
    export default MyMapComponent
    

    【讨论】:

    • 谢谢 - 这已经停止了错误消息 - 但我的指令列表仍然没有像我期望的那样打印。我想知道 this.state.instructionList 在 return 方法中调用是否是错误的?
    • this.state.instructionList 你调用的renderinstructionListMyMapComponent。但是您将数据放入DirectionsComponent 中的instructionList。这就是你在渲染中得到空列表的原因
    • 谢谢 - 我明白你在说什么,我认为这可能是正在发生的事情。但是我不知道我需要的正确语法,而是改为从 DirectionsComponent 访问状态。我试过DirectionsService.route.state.instructionList,但没用。你能给我任何指导吗?抱歉,如果这是一个非常愚蠢的问题,我非常感谢您的帮助!
    猜你喜欢
    • 2020-11-02
    • 2020-02-05
    • 2018-12-29
    • 1970-01-01
    • 1970-01-01
    • 2018-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多