You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React点击Pinpad图片更新输入框字段时遇函数未找到错误

问题修复方案

核心问题分析

  1. CurrentLogin组件未初始化state,且缺失onInputFieldChange函数,导致传递给LoginElement的onChange触发“函数未找到”错误。
  2. LoginElement中useState使用错误,状态与更新函数顺序颠倒,且缺少点击次数的状态变量。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:35:45