简体   繁体   English

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

[英]input's event.target is null within this.setState [React.js]

In my react component I have a file input:在我的反应组件中,我有一个文件输入:

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

and my onFileChange is:我的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
}

This first way of setting the states fails with an error:第一种设置状态的方法失败并出现错误:

Cannot read property 'files' of null

React also gives the following warning: 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

But the last two ways of setting the state give no errors or warnings.但是最后两种设置状态的方法没有给出错误或警告。 Why is this happening?为什么会这样?

The setState function is executed in asynchronous context. setState函数在异步上下文中执行。

By the time the state is updated the e.target reference might or might not be gone.当状态更新时, e.target引用可能会或可能不会消失。

const file = e.target.files[0]; can be used to "remember" the value as in your example.可用于“记住”您的示例中的值。

What is the reason for calling setState with callback ?使用 callback 调用setState的原因是什么? this.setState({ file: e.target.files[0] }) should do the job. this.setState({ file: e.target.files[0] })应该可以完成这项工作。

In your code you are referring to a synthetic event object which no longer holds information about the original DOM event.在您的代码中,您指的是一个合成事件对象,该对象不再包含有关原始 DOM 事件的信息。 React reuses the event objects for performance reasons. React 出于性能原因重用事件对象。

Alternatively you can use:或者,您可以使用:

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

React uses event pooling, you can read more about it in the docs here https://reactjs.org/docs/events.html React 使用事件池,您可以在此处的文档中阅读有关它的更多信息https://reactjs.org/docs/events.html

setState is an asynchronous function setState 是一个异步函数

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

Very simple/basic example to do the same task:执行相同任务的非常简单/基本的示例:

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')
);

I have added console log when the state will be set it will log the file details.我在设置状态时添加了控制台日志,它将记录文件详细信息。 You can see in the log when you select a file the state includes the file data.当您选择一个文件时,您可以在日志中看到状态包括文件数据。

To see the console log you need to right click and inspect and see the Console.要查看控制台日志,您需要右键单击并检查并查看控制台。

Checkout working example here https://jsfiddle.net/1oj3h417/2/在这里结帐工作示例https://jsfiddle.net/1oj3h417/2/

Let me know if you have any doubt如果您有任何疑问,请告诉我

 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM