反应表单元素 onchange 事件在动态生成时不起作用

React form elements onchange event not working when generated dynamically

我正在尝试从数据生成输入列表,并让它们作为受控输入来捕获数据。文本输入似乎被捕获得很好,但是文件输入 onchange 事件出现错误,"TypeError: _this2.handleFileInputChange is not a function"。如果我从箭头函数中取出它,我不会收到错误,但回调仍然不起作用。各位大侠怎么看?

------------编辑------------

实施了将函数定义为箭头函数的建议,这很好,但文件输入似乎仍然没有像其他字段那样触发更改事件。我开始认为这是组件的限制。

还有其他想法吗?谢谢!

import React from "react";
// import { Link } from "gatsby";
import Layout from "../components/layout";
import {Form,InputGroup,Button} from 'bootstrap-4-react'


function camelize(str) {
  return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function(word, index) {
    return index === 0 ? word.toLowerCase() : word.toUpperCase();
  }).replace(/\s+/g, '');
}

const formContent = [
    ["Profile Name","Ex. College soccer profile Spring 2020","text"],
    ["Player Name", "Ex. Jose Greer", "text"],
    ["Player Profile Photo", "Ex. Jose Greer", "file"]
]



class ProfileForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      profileName: '',
      playerName: '',
      profileImageFilename: '',
    };
  }

  

  handleFileInputchange = (e) => {
    console.log(e.target.files[0]);
    this.setState({profileImageFilename: e.target.files[0].filename})
  }

  handleInputChange = (e) => {
    console.log(e)
    this.setState({[e.target]: e.target.value})
  }

  handleSubmit = (e) => {
    console.log(e)
    e.preventDefault()
  }

  createFormGroup(i) {
    const title = i[0],
      placeholder = i[1],
      type = i[2]
    const titleCamelCase = camelize(title);
    if (type === "file") {
      return (
        <>
          <label key={titleCamelCase + "-label"} htmlFor={titleCamelCase}>
            Player Profile Image
          </label>
          <InputGroup key={titleCamelCase + "-group"} mb="3">
            <Form.CustomFile
              required
              onChange={this.handleFileInputChange}
              key={titleCamelCase + "-file"}
              id={titleCamelCase}
              accept=".jpg, .jpeg, .png"
            >
              {this.state.profileImageFilename
                ? this.state.profileImageFilename
                : "Choose an image. ( .jpg, .jpeg, .png, .gif )"}
            </Form.CustomFile>
          </InputGroup>
        </>
      );
    }

    return (
      <>
        <label key={titleCamelCase + "-label"} htmlFor={titleCamelCase}>
          {title}
        </label>
        <Form.Input
          key={titleCamelCase + "-input"}
          mb="3"
          required
          type={type}
          id={titleCamelCase}
          placeholder={placeholder}
          onChange={this.handleInputChange}
          valule={this.state[titleCamelCase]}
        />
      </>
    );
  }

  render() {
    return (
      <Layout>
        <Form onSubmit={this.handleSubmit}>
          <Form.Group>
            {/* {formContent.map(function(i){this.createFormGroup(i)}.bind(this))} */}
            {formContent.map((i)=>this.createFormGroup(i))}
          </Form.Group>
          <Button primary type="submit">
            Submit
          </Button>
        </Form>
      </Layout>
    );
  }
}

export default ProfileForm

问题

class 组件的 this 未绑定到 handleFileInputchange 回调处理程序。

解决方案

您应该在 constructor 中将 this 绑定到 handleFileInputchange 或将其声明为箭头函数。

constructor(props) {
  super(props);
  this.state = {
    profileName: '',
    playerName: '',
    profileImageFilename: '',
  };

  this.handleFileInputchange = this.handleFileInputchange.bind(this);
}

handleFileInputchange = (e) => {
  console.log(e);
  this.setState({ profileImageFilename: e.target.file[0].filename });
}

您还可以安全地删除匿名回调并直接传递 this.handleFileInputChange,因为 onChange 事件处理程序和您的回调具有相同的函数签名:

onChange={this.handleFileInputChange}

更新

我用你的代码创建了一个 codesandbox。奇怪的是,我也没有看到任何 onChange 回调触发(控制台日志),我什至添加了一个 componentDidUpdate 来记录状态更新,这也没有触发。我可以添加一个新文件并看到带有我选择的文件名的文本工具提示,但 UI 中没有任何更新。如果您的 bootstrap 输入仍然导致问题,我建议实施原始输入元素。

@drew 我最终不得不使用 标准输入 元素,因为我找不到任何证据表明反应 bootstrap 组件触发了更改事件。谢谢您的意见。您可能需要修改您的答案,因为正确的部分已在您的评论中。