开发者问题收集

无法读取为空的属性“上下文”

2017-05-07
8711

我一直在学习 Egghead 的“构建你的第一个生产质量 React 应用程序”,一切都很顺利,直到第 17 课,你应该使用 context 来创建你自己的自制路由器组件。据我所知,我做的事情和课程中完全一样,但是当我点击其中一个 Link 组件时,出现此控制台错误:

Link.js:11 Uncaught TypeError: Cannot read property 'context' of null
at handleClick (http://localhost:3000/static/js/bundle.js:33792:12)
at Object.ReactErrorUtils.invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:17162:17)
at executeDispatch (http://localhost:3000/static/js/bundle.js:16945:22)
at Object.executeDispatchesInOrder (http://localhost:3000/static/js/bundle.js:16968:6)
at executeDispatchesAndRelease (http://localhost:3000/static/js/bundle.js:16356:23)
at executeDispatchesAndReleaseTopLevel (http://localhost:3000/static/js/bundle.js:16367:11)
at Array.forEach (native)
at forEachAccumulated (http://localhost:3000/static/js/bundle.js:17265:10)
at Object.processEventQueue (http://localhost:3000/static/js/bundle.js:16570:8)
at runEventQueueInBatch (http://localhost:3000/static/js/bundle.js:24192:19)

链接组件如下所示:

import React, { Component } from 'react';

export class Link extends Component {
  static contextTypes = {
    route: React.PropTypes.string,
    linkHandler: React.PropTypes.func,
  }

  handleClick(e) {
    e.preventDefault();
    this.context.linkHandler(this.props.to)
  }

  render() {
    const activeClass = this.context.route === this.props.to ? 'active' : '';
    return <a href="#" className={activeClass} onClick={this.handleClick}>{this.props.children}</a>
  }
}

Link.propTypes = {
  to: React.PropTypes.string.isRequired
}

路由器组件如下所示:

import React, { Component } from 'react';

const getCurrentPath = () => {
  const path = document.location.pathname;
  return path.substring(path.lastIndexOf('/'));
}

export class Router extends Component {
  state = {
    route: getCurrentPath()
  }

  handleLinkClick = (route) => {
    this.setState({ route }); // same as { route: route }
    history.pushState(null, '', route);
  }

  static childContextTypes = {
    route: React.PropTypes.string,
    linkHandler: React.PropTypes.func,
  };

  getchildContext() {
    return {
      route: this.state.route,
      linkHandler: this.handleLinkClick,
    };
  }

  render() {
    return <div>{this.props.children}</div>
  }
}

知道是什么原因导致了这个问题吗?

感谢您提供正确的方向!

编辑:

按照我得到的建议(谢谢!),我将 handleClick 绑定在构造函数中(使用箭头函数的结果相同)并验证该函数是否按预期调用,但现在我收到了不同的错误:

Uncaught TypeError: this.context.linkHandler is not a function
at Link.handleClick (http://localhost:3000/static/js/bundle.js:33707:21)
at Object.ReactErrorUtils.invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:17162:17)
at executeDispatch (http://localhost:3000/static/js/bundle.js:16945:22)
at Object.executeDispatchesInOrder (http://localhost:3000/static/js/bundle.js:16968:6)
at executeDispatchesAndRelease (http://localhost:3000/static/js/bundle.js:16356:23)
at executeDispatchesAndReleaseTopLevel (http://localhost:3000/static/js/bundle.js:16367:11)
at Array.forEach (native)
at forEachAccumulated (http://localhost:3000/static/js/bundle.js:17265:10)
at Object.processEventQueue (http://localhost:3000/static/js/bundle.js:16570:8)
at runEventQueueInBatch (http://localhost:3000/static/js/bundle.js:24192:19)
3个回答

除了需要将函数绑定到 this 之外,如果您绑定了类中不再存在的函数,也可能会发生此错误:

export class Example extends Component {
    constructor(props) {
        super(props);
        this.functionDoesNotExistAnymore = this.functionDoesNotExistAnymore.bind(this);
    }

    // functionDoesNotExistAnymore() {}
}
user1781495
2017-06-14

这是在 React 中使用 ES6 时常见的问题。您需要将 handleClick 函数绑定到 React 组件的上下文。您可以在组件定义中使用箭头函数来绑定上下文,如下所示

export class Link extends Component {
  static contextTypes = {
    route: React.PropTypes.string,
    linkHandler: React.PropTypes.func,
  }

  handleClick = (e) => {
    e.preventDefault();
    this.context.linkHandler(this.props.to)
  }

  render() {
    const activeClass = this.context.route === this.props.to ? 'active' : '';
    return <a href="#" className={activeClass} onClick={this.handleClick}>{this.props.children}</a>
  }
}

或者您可以在构造函数中绑定它,例如

export class Link extends Component {
   constructor(props) {
       super(props);
       this.handleClick = this.handleClick.bind(this);
   }

   ...

}

或者您可以在调用时绑定它

onClick={() => this.handleClick()}>

or

onClick={this.handleClick.bind(this)}
Shubham Khatri
2017-05-08

为了清楚地回答这个问题,其他人有大量的额外信息可能会让你误入歧途。

引用

You need to bind this to handleClick. You can either do this in a constructor or in onClick (not recommended). onClick={this.handleClick.bind(this)} . Or use an arrow function for handleClick. const handleClick = () = > { }.

Norm Crandall (来自评论)

Jason
2017-07-04