[英]Getting a typeError in React saying this.props is not a function when child component tries to call passed function
When I try to call the passed function from the child function, I get the following error 当我尝试从子功能调用传递的功能时,出现以下错误
Uncaught TypeError: this.props.addHours is not a function 未捕获的TypeError:this.props.addHours不是函数
Here's a codepen with the issue: example 这是一个带有问题的codepen: 示例
Here's the code with my components: 这是我的组件的代码:
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>;
}
}
Basically, I'm passing the child component a function so I'm not sure why it doesn't think the prop is one. 基本上,我给子组件传递了一个函数,所以我不确定为什么它不认为prop是一个。 I'm pretty sure I've bond everything correctly, which was my first guess, but perhaps not. 我很确定我已经正确绑定了所有内容,这是我的第一个猜测,但也许不是。 It would be greatly appreciated if someone could point out what I'm doing wrong! 如果有人能指出我做错了,将不胜感激!
you do not use an arrow function in this.state.flies.map
so it does not have the scope needed to get the context for this
你不使用箭头功能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>;
})}
This is happening because you are using this
inside a function() {}
. 发生这种情况,因为你正在使用this
一个内部function() {}
which means the addHours
function is not in scope for the available this
. 这意味着addHours
函数不在可用this
范围内。 Depending on if you are compiling this or not you can do one of the following: 根据您是否进行编译,可以执行以下操作之一:
If you are open to using an arrow function: 如果您愿意使用箭头功能:
{
this.state.flies.map(fly => {
return (
<li>
<Fly
addHours={this.addHours}
name={fly.name}
hours={fly.hours}
fish={fly.fish}
/>
</li>;
})
}
if you want to continue using function() {}
: 如果您想继续使用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>;
})
}
The this
inside your this.state.flies.map
is not the one you are expected. 在this
里面你this.state.flies.map
是不是你所期望的一个。 You should defined varibable before calling map to reference the correct this: 您应在调用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>
...
You have 2 main issues here: 您在这里有2个主要问题:
The map function is shadowing the this
context. 地图功能正在遮盖this
上下文。 You can extract it to an external method and bind it as well in the constructor 您可以将其提取到外部方法,并在构造函数中将其绑定
Or use an arrow function so it will use a lexical context for the this
: 或使用箭头函数,以便this
使用词法上下文:
this.state.flies.map((fly) => { return <li><Fly addHours={this.addHours} name={fly.name} hours={fly.hours} fish={fly.fish} /></li>; })}
Another issue (error) you will face later is that you are not passing the event ( e
) from the Fly
method to the parent: 您稍后将面临的另一个问题(错误)是您没有将事件( e
)从Fly
方法传递给父方法:
doAddHours(e) { this.props.addHours(e) }
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'));
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; }
<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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.