it-swarm.com.ru

входной файл event.target имеет значение null в this.setState [React.js]

В моем компоненте реакции у меня есть файл ввода:

<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

Но последние два способа установки состояния не дают ошибок или предупреждений. Почему это происходит?

4
S_Farsai

Функция setState выполняется в асинхронном контексте. 

Ко времени обновления состояния ссылка e.target может исчезнуть или не исчезнуть.

const file = e.target.files[0]; может использоваться для «запоминания» значения, как в вашем примере.

9
Kunukn

В чем причина вызова setState с обратным вызовом? 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

2
dev-null

React использует пул событий, вы можете узнать больше об этом в документации здесь https://reactjs.org/docs/events.html

setState - асинхронная функция

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

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>

0
Mikhail Katrin

Очень простой/базовый пример для выполнения той же задачи: 

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/

Дайте мне знать, если у вас есть какие-либо сомнения

0
thakurinbox