在React中获取typeError,当子组件尝试调用传递的函数时,this.props不是函数

时间:2018-01-02 15:59:00

标签: javascript reactjs

当我尝试从子函数调用传递的函数时,我收到以下错误

  

未捕获的TypeError:this.props.addHours不是函数

这是一个包含问题的代码:example

以下是我的组件的代码:

class Application extends React.Component {
  constructor(props) {
    super(props);

    this.handleSubmit = this.handleSubmit.bind(this);
    this.addHours = this.addHours.bind(this)

    this.state = {
      flies:[{
      name: 'Elk Hair Caddis',
      hours: 10,
      fish: 12
      },
      {
      name: 'Adams',
      hours: 6,
      fish: 4
      }
      ]
    };
  }

  handleSubmit(event) {
    alert('A fly was submitted');
    event.preventDefault();

    let subName = document.getElementById("subName").value
    let subHours = document.getElementById("subHours").value
    let subFish = document.getElementById("subFish").value

    document.forms[0].reset()

   function flyMaker(name, hours, fish) {
      this.name = name
      this.hours = hours
      this.fish = fish
    }

    let myFly = new flyMaker(subName, subHours, subFish)

    let tempState = this.state.flies
    tempState.push(myFly)
    this.setState(tempState)
  }

 addHours(e){
    e.preventDefault()
    alert('hey')
    console.log('hey')
  }

  render() {
    return <div>
      <h1>Fly List</h1>
         <ul>
          {this.state.flies.map(function(fly){
            return <li><Fly addHours={this.addHours} name={fly.name} hours={fly.hours} fish={fly.fish} /></li>;
          })}
        </ul>
      <div id='addFly'>
        <h1>Add a Fly</h1>
        <form onSubmit={this.handleSubmit}>
        <p>Name:</p>
        <input id='subName' type='text'/>
        <p>Hours:</p>
        <input id='subHours' type='text'/>
         <p>Fish Caught:</p>
        <input id='subFish' type='text'/>
          <br/>
        <input type='submit' value='submit' />
        </form>
      </div>
    </div>;
  }
}

class Fly extends React.Component { 
  constructor(props) {
    super(props);
    this.doAddHours = this.doAddHours.bind(this)

  }

  doAddHours() {
    this.props.addHours()
  }

  render() {
    return <div>
      <p>{this.props.name}</p>
      <div>Hours fished: {this.props.hours}</div>
      <div className='increment' onClick={this.doAddHours}>+</div><div className='increment'>-</div>
      <div>Fish Caught: {this.props.fish}</div>
      <div className='increment'>+</div><div className='increment'>-</div>
    </div>;
  }
}

基本上,我将子组件传递给一个函数,所以我不确定为什么它不认为prop是一个。我很确定我已经把所有东西都绑定了,这是我的第一个猜测,但也许不是。如果有人能够指出我做错了什么,我将不胜感激!

4 个答案:

答案 0 :(得分:3)

您没有在this.state.flies.map中使用箭头功能,因此它没有获取this的上下文所需的范围

{this.state.flies.map( fly => {
        return <li><Fly addHours={this.addHours} name={fly.name} hours={fly.hours} fish={fly.fish} /></li>;
      })}

答案 1 :(得分:1)

这种情况正在发生,因为您在this内使用function() {}。这意味着addHours函数不在可用this的范围内。根据您是否正在编译,您可以执行以下操作之一:

如果您愿意使用箭头功能:

{
  this.state.flies.map(fly => {
    return (
      <li>
        <Fly
          addHours={this.addHours}
          name={fly.name}
          hours={fly.hours}
          fish={fly.fish}
        />
      </li>;
  })
}

如果您想继续使用function() {}

// At the top of the render function somewhere
var _this = this;

// In your return
{
  this.state.flies.map(function(fly) {
    return (
      <li>
        <Fly
          addHours={_this.addHours}
          name={fly.name}
          hours={fly.hours}
          fish={fly.fish}
        />
      </li>;
  })
}

答案 2 :(得分:0)

this内的this.state.flies.map不是您所期望的那个。 您应该在调用map之前定义varibable以引用正确的:

render() {

const _this = this;

return <div>
  <h1>Fly List</h1>
     <ul>
      {this.state.flies.map(function(fly){
        return <li><Fly addHours={_this.addHours} name={fly.name} hours={fly.hours} fish={fly.fish} /></li>;
      })}
    </ul>
...

答案 3 :(得分:0)

这里有两个主要问题:

  1. 地图功能正在隐藏this上下文。你可以提取 它是一个外部方法,并在构造函数中绑定它 或者使用箭头函数,因此它将使用词汇上下文 this

    this.state.flies.map((fly) => {
    
              return <li><Fly addHours={this.addHours} name={fly.name} hours={fly.hours} fish={fly.fish} /></li>;
            })}
    
  2. 稍后您将面临的另一个问题(错误)是您不是 将事件(e)从Fly方法传递给父级:

      doAddHours(e) {
        this.props.addHours(e)
      }
    

    <小时/> 以下是代码的运行示例:

  3. &#13;
    &#13;
    class Application extends React.Component {
      constructor(props) {
        super(props);
    
        this.handleSubmit = this.handleSubmit.bind(this);
        //this.addHours = this.addHours.bind(this)
    
        this.state = {
          flies: [{
            name: 'Elk Hair Caddis',
            hours: 10,
            fish: 12
          },
          {
            name: 'Adams',
            hours: 6,
            fish: 4
          }
          ]
        };
      }
    
      handleSubmit(event) {
        //alert('A fly was submitted');
        event.preventDefault();
    
        let subName = document.getElementById("subName").value
        let subHours = document.getElementById("subHours").value
        let subFish = document.getElementById("subFish").value
    
        document.forms[0].reset()
    
        function flyMaker(name, hours, fish) {
          this.name = name
          this.hours = hours
          this.fish = fish
        }
    
        let myFly = new flyMaker(subName, subHours, subFish)
    
        let tempState = this.state.flies
        tempState.push(myFly)
        this.setState(tempState)
      }
    
      addHours = (e) => {
        e.preventDefault()
        //alert('hey')
        console.log('hey')
      }
    
      render() {
        return <div>
          <h1>Fly List</h1>
          <ul>
            {this.state.flies.map((fly) => {
              
              return <li><Fly addHours={this.addHours} name={fly.name} hours={fly.hours} fish={fly.fish} /></li>;
            })}
          </ul>
          <div id='addFly'>
            <h1>Add a Fly</h1>
            <form onSubmit={this.handleSubmit}>
              <p>Name:</p>
              <input id='subName' type='text' />
              <p>Hours:</p>
              <input id='subHours' type='text' />
              <p>Fish Caught:</p>
              <input id='subFish' type='text' />
              <br />
              <input type='submit' value='submit' />
            </form>
          </div>
        </div>;
      }
    }
    
    class Fly extends React.Component {
      constructor(props) {
        super(props);
        this.doAddHours = this.doAddHours.bind(this)
    
      }
    
      doAddHours(e) {
        this.props.addHours(e)
      }
    
      render() {
        return <div>
          <p>{this.props.name}</p>
          <div>Hours fished: {this.props.hours}</div>
          <div className='increment' onClick={this.doAddHours}>+</div><div className='increment'>-</div>
          <div>Fish Caught: {this.props.fish}</div>
          <div className='increment'>+</div><div className='increment'>-</div>
        </div>;
      }
    }
    
    /*
     * Render the above component into the div#app
     */
    ReactDOM.render(<Application />, document.getElementById('app'));
    &#13;
    html, body {
      height: 100%;
    }
    
    body {
      background: #333;
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-pack: center;
          -ms-flex-pack: center;
              justify-content: center;
      font-family: Helvetica Neue;
    }
    
    h1 {
      font-size: 2em;
      color: #eee;
      display: inline-block;
    }
    
    a {
      color: white;
    }
    
    p {
      margin-top: 1em;
      text-align: center;
      color: #aaa;
    }
    
    .increment {
      display: inline-block;
      padding: 10px;
      background-color: black;
      color: white;
      margin: 4px;
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="app"></div>
    &#13;
    &#13;
    &#13;