input 的 event.target 在 this.setState [React.js] 中为 null

IT技术 javascript html reactjs
2021-03-27 20:31:23

在我的react组件中,我有一个文件输入:

<input type="file" onChange={this.onFileChange.bind(this)} />` 

我的onFileChange是:

onFileChange(e) {
  let file = e.target.files[0];
  this.setState(() => ({ file: e.target.files[0] })); //doesnt work
  // this.setState(() => ({ file })); //works
  // this.setState({ file: e.target.files[0] }); //works
}

第一种设置状态的方法失败并出现错误:

Cannot read property 'files' of null

React 还给出了以下警告:

This synthetic event is reused for performance reasons. If you're 
seeing this, you're accessing the property 'target' on a 
released/nullified synthetic event

但是最后两种设置状态的方法没有给出错误或警告。为什么会这样?

5个回答

setState函数在异步上下文中执行。

到状态更新时,e.target引用可能会或可能不会消失。

const file = e.target.files[0]; 可用于“记住”您的示例中的值。

file变量是在() => ({ file })函数声明的闭包中声明的,这就是file稍后可以访问的原因
2021-05-31 20:31:23
啊!谢谢。我没有意识到 setState 是异步的
2021-06-04 20:31:23

setState使用 callback调用的原因是什么this.setState({ file: e.target.files[0] })应该做的工作。

在您的代码中,您指的是一个合成事件对象,该对象不再包含有关原始 DOM 事件的信息。React 出于性能原因重用事件对象。

或者,您可以使用:

let file = e.target.files[0]; const files = e.target.files this.setState(() => ({ file: files[0] })); //doesnt work

所以this.setState(() => {}) 箭头函数是异步的,而this.setState({})不是?从我了解到反应形式的来源,我被告知前一种方法是标准。我不知道这是异步的
2021-06-08 20:31:23
不幸的是,我使用了这个词。React 中的所有状态更新都是异步的。我所说的“异步”实际上是将更新程序回调而不是构造对象传递给setState. 我认为这只是 API 差异,我发现setState({})它更具可读性。updater当你计算基础上的实际状态(如增加)新的状态回调必须使用。为什么setState(updater)在文档中首先提到的原因可能与强迫人们认为它是许多人往往忘记(或一开始不知道)的异步操作有关。
2021-06-10 20:31:23

React 使用事件池,您可以在此处的文档中阅读有关它的更多信息https://reactjs.org/docs/events.html

setState 是一个异步函数

this.setState(() => ({ file })); // is correct

执行相同任务的非常简单/基本的示例:

class Hello extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
    file: ''
    };
  }

  render() {
    return <div>
    <input type='file' onChange={(e) => {
    this.setState({file: e.target.files[0]}, () => {
        console.log('state', this.state);
    })
    }} />
    </div>;
  }
}

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);

我在设置状态时添加了控制台日志,它将记录文件详细信息。当您选择文件时,您可以在日志中看到状态包括文件数据。

要查看控制台日志,您需要右键单击并检查并查看控制台。

在此处结帐工作示例https://jsfiddle.net/1oj3h417/2/

如果您有任何疑问,请告诉我

这是因为 react 重用了它的事件
2021-05-24 20:31:23
谢谢。我有一个工作版本,你可以在其他两个被注释掉的 set state 方法中看到。我发帖是因为我很好奇为什么第一种方法不起作用
2021-06-07 20:31:23

class Example extends React.Component {

  onFileChange = e => {
    let file = e.target.files[0];
    this.setState(() => ({ file: file }));
  }
  render() {
    return <input type="file" onChange={this.onFileChange} />;
  }
}

ReactDOM.render(
  <Example />,
  document.getElementById('root')
);
<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="root">
</div>