ReactJS与ES6:当我通信两个组件时,“this.props不是一个函数”

29

我正在使用ReactJS和ES6,但是我在通过props通信子组件和父组件方面遇到了一些问题。以下是我的一种方法示例:

class SearchBar extends React.Component {
  handler(e){
    this.props.filterUser(e.target.value);
  }

  render () {
  return <div>
    <input type='text' className='from-control search-bar' placeholder='Search' onChange={this.handler} />
  </div>
  }
}


export default class User extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name: '', age: '', filter: ''};
  } 

  filterUser(filterValue){
    this.setState({
      filter: filterValue
    });
  }

  render() {
    return <div>
      <SearchBar filterUser={this.filterUser} />
      <span>Value: {this.state.filter}</span>
    </div>
  }
}

这个报错信息是 Uncaught TypeError: this.props.filterUser is not a function

有什么想法吗?可能需要绑定(Binding)吗?

[编辑] 解决方案(感谢 @knowbody 和 @Felipe Skinner):

我在构造函数中缺少绑定。在 SearchBar 构造函数中添加绑定之后完美解决。

使用 React.createClass() (ES5),它会自动为您的函数进行 this 绑定。 在 ES6 中需要手动绑定 this。更多信息请参见https://facebook.github.io/react/docs/reusable-components.html#es6-classes

4个回答

23

如果您的构造函数中缺少绑定,那么您需要添加它。如果您在构造函数中没有使用 props ,则不需要传递它们。另外,您需要 import {PropTypes} from 'react'

class SearchBar extends React.Component {

  constructor() {
    super();
    this.handler = this.handler.bind(this);
  }

  handler(e){
    this.props.filterUser(e.target.value);
  }

  render () {
    return (
      <div>
        <input type='text' className='from-control search-bar' placeholder='Search' onChange={this.handler} />
      </div>
    );
  }
}


export default class User extends React.Component {
  constructor() {
    super();
    this.filterUser = this.filterUser.bind(this);
    this.state = { name: '', age: '', filter: '' };
  } 

  filterUser(filterValue){
    this.setState({
      filter: filterValue
    });
  }

  render() {
    return ( 
      <div>
        <SearchBar filterUser={this.filterUser} />
        <span>Value: {this.state.filter}</span>
      </div>
    );
  }
}

不错!它可以工作,但是像那样设置propTypes会抛出“意外的标记”错误。SearchBar.propTypes = { filterUser: React.PropTypes.func };更好。 - skozz
抱歉,我已经修复了。之前我使用的是ES7的方式。请参考https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#es7-property-initializers。 - knowbody
1
当然可以。无论如何,在不设置propTypes的情况下也可以工作,你是对的:我在构造函数中缺少绑定。在SearchBar构造函数中进行绑定可以完美解决问题。 - skozz
1
@skozz 很高兴我能帮到你。 - knowbody
嘿,我正在尝试在React Native中实现类似的功能,但它会抛出错误“this.props.filterUser不是一个函数”。有人能告诉我我做错了什么吗?我的代码与上面的解决方案类似。 - Abhinandan Sahgal
@AbhinandanSahgal,你能给我展示一下你的代码吗?或者把它粘贴到gist上,这样我就可以在那里评论了? - knowbody

6

当你使用React.createClass()时,它会自动为你的函数绑定this。

由于你正在使用ES6类语法,你需要自己进行这些绑定。以下是两种选项:

render() {
    return <div>
      <SearchBar filterUser={this.filterUser.bind(this)} />
      <span>Value: {this.state.filter}</span>
    </div>
  }

或者你可以像这样在构造函数中绑定它:
constructor(props) {
    super(props);
    this.state = {name: '', age: '', filter: ''};
    this.filterUser = this.filterUser.bind(this);
  } 

你可以在文档中了解这个: https://facebook.github.io/react/docs/reusable-components.html#es6-classes 请注意,这两个选项是互斥的。

2
最初的回答: 在我的情况下,我导入组件的方式不正确。 我有组件“HomeAdmin”和“Register”。
我在HomeAdmin.js中有这个: import { Register } from "/path/to/register" 更改为以下内容就可以了: import Register from "/path/to/register"

0

这也可能是一个误导出口:

错误的写法: export function 名称...

export default 名称

正确的写法:

function 名称 export default 名称


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接