In my react component I have a file input:
`
and my onFileChan
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>
What is the reason for calling setState
with callback ? this.setState({ file: e.target.files[0] })
should do the job.
In your code you are referring to a synthetic event object which no longer holds information about the original DOM event. React reuses the event objects for performance reasons.
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
setState is an asynchronous function
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/
Let me know if you have any doubt
The setState
function is executed in asynchronous context.
By the time the state is updated the e.target
reference might or might not be gone.
const file = e.target.files[0];
can be used to "remember" the value as in your example.