React.js子组件通过props调用父组件函数报错及修复方法
问题描述
尝试通过子组件修改父组件状态,已在父组件创建handleDelete函数并尝试通过props传递给子组件Product,但项目运行时出现错误:TypeError: this.props.handleDelete is not a function。
相关代码
Products组件(父组件)
import React, { Component } from 'react'; import Product from './product'; class Products extends Component { state = { products: [ { id: 1, count: 2, productName: 'laptp' }, { id: 2, count: 1, productName: 'phone' }, { id: 3, count: 4, productName: 'airpods' } ] } render() { return ( <> {this.state.products.map((p, index) => ( <Product onClick={this.handleDelete} id={p.id} key={index} productName={p.productName} count={p.count} > Lorem, ipsum dolor sit amet consectetur adipisicing elit. </Product> ))} </> ); } handleDelete = (productId) => { console.log(productId); } } export default Products;
Product组件(子组件)
import { Component } from "react"; class Product extends Component { state = { count: this.props.count, productName: this.props.productName } render() { return ( <div> <span className="m-2 text-info"> {this.props.productName}</span> <span className="m-2 badge bg-primary">{this.format(this.count)}</span> <button onClick={this.handleIncrement} className="m-2 btn btn-sm btn-success">+</button> <button onClick={this.handleDecrement} className="m-2 btn btn-sm btn-warning">-</button> <button onDelete={this.handleDelete()} className="m-2 btn btn-sm btn-danger">delete</button> <p>{this.props.children}</p> </div> ); } handleIncrement = () => { const { count } = this.state; this.setState({ count: count + 1 }); } handleDecrement = () => { const { count } = this.state; this.setState({ count: count - 1 }); } handleDelete = () => { this.props.handleDelete(this.props.id) } format() { if (this.state.count === 0) { return "zero"; } else { return this.state.count; } } } export default Product;
index.js
import Products from "./components/products"; import ReactDOM from "react-dom"; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<Products />);
错误栈
this.props.handleDelete is not a function TypeError: this.props.handleDelete is not a function at Product.handleDelete (http://localhost:3000/main.a60ab9ca1348fe27abe1.hot-update.js:47:18) at Product.render (http://localhost:3000/main.a60ab9ca1348fe27abe1.hot-update.js:83:23) at finishClassComponent (http://localhost:3000/static/js/bundle.js:23142:35) at updateClassComponent (http://localhost:3000/static/js/bundle.js:23099:28) at beginWork (http://localhost:3000/static/js/bundle.js:24725:20) at beginWork$1 (http://localhost:3000/static/js/bundle.js:29665:18) at performUnitOfWork (http://localhost:3000/static/js/bundle.js:28935:16) at workLoopSync (http://localhost:3000/static/js/bundle.js:28858:9) at renderRootSync (http://localhost:3000/static/js/bundle.js:28831:11) at recoverFromConcurrentError (http://localhost:3000/static/js/bundle.js:28323:24)
问题原因
- props传递名称不匹配:父组件给子组件传递的属性是
onClick,但子组件中尝试调用的是this.props.handleDelete,名称不对应导致子组件无法获取到目标函数。 - 按钮事件绑定错误:子组件中delete按钮使用
onDelete={this.handleDelete()},直接执行了函数而非传递函数引用,会在组件渲染时立即触发handleDelete,此时因第一个问题导致函数不存在,直接抛出错误;同时HTML原生按钮没有onDelete事件,需使用标准的onClick。 - format方法调用错误:子组件中
format(this.count)里的this.count未定义,应使用this.state.count。
修复方案
1. 修正父组件(Products)
将传递给子组件的props名称从onClick改为handleDelete,确保名称匹配,并补充实际删除逻辑:
import React, { Component } from 'react'; import Product from './product'; class Products extends Component { state = { products: [ { id: 1, count: 2, productName: 'laptp' }, { id: 2, count: 1, productName: 'phone' }, { id: 3, count: 4, productName: 'airpods' } ] } render() { return ( <> {this.state.products.map((p, index) => ( {/* 修改props名称为handleDelete */} <Product handleDelete={this.handleDelete} id={p.id} key={index} productName={p.productName} count={p.count} > Lorem, ipsum dolor sit amet consectetur adipisicing elit. </Product> ))} </> ); } handleDelete = (productId) => { // 过滤掉对应id的产品,更新父组件状态 this.setState(prevState => ({ products: prevState.products.filter(product => product.id !== productId) })); console.log(productId); } } export default Products;
2. 修正子组件(Product)
- 修正delete按钮的事件绑定,传递函数引用而非立即执行,同时改用标准
onClick事件; - 修正format方法的调用参数,传入正确的
this.state.count:
import { Component } from "react"; class Product extends Component { state = { count: this.props.count, productName: this.props.productName } render() { return ( <div> <span className="m-2 text-info"> {this.props.productName}</span> {/* 修正format的参数为this.state.count */} <span className="m-2 badge bg-primary">{this.format(this.state.count)}</span> <button onClick={this.handleIncrement} className="m-2 btn btn-sm btn-success">+</button> <button onClick={this.handleDecrement} className="m-2 btn btn-sm btn-warning">-</button> {/* 改用onClick事件,传递函数引用而非立即执行 */} <button onClick={this.handleDelete} className="m-2 btn btn-sm btn-danger">delete</button> <p>{this.props.children}</p> </div> ); } handleIncrement = () => { const { count } = this.state; this.setState({ count: count + 1 }); } handleDecrement = () => { const { count } = this.state; this.setState({ count: count - 1 }); } handleDelete = () => { this.props.handleDelete(this.props.id) } format(count) { if (count === 0) { return "zero"; } else { return count; } } } export default Product;
内容的提问来源于stack exchange,提问作者hmahdavi
相关产品推荐
相关产品推荐

