React点击Pinpad图片更新输入框字段时遇函数未找到错误
问题修复方案
核心问题分析
CurrentLogin组件未初始化state,且缺失onInputFieldChange函数,导致传递给LoginElement的onChange触发“函数未找到”错误。LoginElement中useState使用错误,状态与更新函数顺序颠倒,且缺少点击次数的状态变量。Pinpad的点击事件处理函数未实现业务逻辑,输入框未与状态绑定。
修复步骤
1. 完善CurrentLogin组件
- 在
constructor中初始化state,存储用户输入值。 - 实现
onInputFieldChange函数,兼容原有文本/密码输入的变更逻辑。 - 修正
onChange传递方式,避免组件渲染时立即执行函数。
2. 修复LoginElement的Pinpad逻辑
- 为Pinpad添加两个状态:
imageIds(存储逗号分隔的ID)和clickCount(存储点击次数)。 - 实现
onPinPadClick函数,点击时更新两个状态:- 若
imageIds为空,直接赋值当前ID;否则追加, + 当前ID。 - 点击次数每次自增1。
- 若
- 将输入框与对应状态绑定,第一个输入框展示ID序列,第二个展示点击次数(设置为只读避免用户修改)。
修改后的完整代码
Login.js
import React from 'react'; import { connect } from 'react-redux' import LoginElement from './LoginElement' class CurrentLogin extends React.Component { constructor(props) { super(props); // 初始化state存储用户输入值 this.state = { userInputValues: {} }; // 绑定函数上下文 this.onInputFieldChange = this.onInputFieldChange.bind(this); } // 实现输入框变更处理函数 onInputFieldChange(fieldId) { return (e) => { this.setState(prevState => ({ userInputValues: { ...prevState.userInputValues, [fieldId]: e.target.value } })); }; } render() { return ( <div> {this.props.credentials.map(credentialElement => ( <LoginElement data={credentialElement} key={credentialElement.fieldID} inputValue={this.state.userInputValues[credentialElement.fieldID] || ''} onChange={this.onInputFieldChange(credentialElement.fieldID)} /> ))} </div> ); } } // 根据你的redux配置调整state映射 const mapStateToProps = state => ({ credentials: state.credentials }); export default connect(mapStateToProps)(CurrentLogin);
LoginElement.js
import React, { useState } from 'react'; import parse from 'html-react-parser'; const LoginElement= (props) => { switch (props.data.type.toLowerCase()) { case "text": return ( <div className="form-group"> <label style={{display: "block"}}>{props.data.name}</label> {props.data.description && <span>{parse(props.data.description)}</span> } <input type="text" className="form-control" value={props.inputValue} onChange={props.onChange} /> </div> ); case "password": return ( <div className="form-group"> <label>{props.data.name}</label> <input type="password" className="form-control" value={props.inputValue} onChange={props.onChange} /> </div> ); case "pinpad": // 初始化Pinpad的两个状态:ID序列和点击次数 const [imageIds, setImageIds] = useState(''); const [clickCount, setClickCount] = useState(0); // 实现Pinpad点击逻辑 const onPinPadClick = key => () => { // 更新ID序列:空则直接赋值,否则追加逗号分隔 const newImageIds = imageIds ? `${imageIds},${key}` : key; setImageIds(newImageIds); // 更新点击次数 setClickCount(prevCount => prevCount + 1); }; const pinPadImages = props.data.pinpads; return ( <div className="form-group"> <label style={{display: "block"}}>{props.data.name}</label> <input type="hidden" className="form-control" /> {/* 第一个输入框:展示逗号分隔的ID */} <input type="text" className="form-control" value={imageIds} readOnly // 设置只读,避免用户手动修改 /> {/* 第二个输入框:展示点击次数 */} <input type="text" className="form-control" value={clickCount} readOnly style={{marginTop: '8px'}} /> <div className="pin-pad-container"> {Object.keys(pinPadImages).map(index => ( <img key={index} src={pinPadImages[index].src} alt={`Pinpad key ${index}`} width={pinPadImages[index].width} height={pinPadImages[index].height} data-field-id={index} data-field-type={pinPadImages[index].type} className="pinpad" onClick={onPinPadClick(index)} /> ))} </div> </div> ); default: return null; } } export default LoginElement;
额外说明
- 为Pinpad图片添加
key属性,避免React列表渲染警告。 - 补充图片
alt文本,提升页面可访问性。 - 第二个输入框设置
readOnly,因为点击次数为自动统计值,无需用户输入。
内容的提问来源于stack exchange,提问作者Jaydp
相关产品推荐
相关产品推荐

