Реакция, вызов функции без сохранения состояния для организации кода, но как это связать? - PullRequest
0 голосов
/ 03 декабря 2018

С учетом этого кода реакции

<form onSubmit={this.onSubmit}>

, который выполняет функцию

import {onFormSubmit} from '../onFormSubmit'
.....
onSubmit = (e) => {
    // here I have access to "this" thanks to the arrow functions
    e.preventDefault()
    onFormSubmit(this.state.files, this.props)
}

Где onFormSubmit находится в другом файле как функция без сохранения состояния

export const onFormSubmit = async (files,props) => {
    this.setState(... // error
}

Я вижу, что теряю «this», когда я нахожусь в функции onFormSubmit, так что там я не могу, например, выполнить this.setState

Тогда, как я могу сохранить доступ к этому?

Вариант A , как сказано в ответах, состоит в том, чтобы забыть стрелки:

onSubmit = (e) => {
    // here I have access to "this" thanks to the arrow functions
    e.preventDefault()
    onFormSubmit.bind(this)(this.state.files, this.props)
}

.

export async onFormSubmit = function(files,props) {
    this.setState(... // now it works
}

OptionB , для передачи this в качестве переменной

onSubmit = (e) => {
    // here I have access to "this" thanks to the arrow functions
    e.preventDefault()
    let self = this
    onFormSubmit(self)
}

Опция C , для переопределения onFormSubmit в качестве средства обновления, как сказано в ответах, но не для опцииздесь, поскольку функция не только обновляет состояние, например:

export const onFormSubmit = async (files,props) => {
    if (files) {
      ... upload file ... parse file ...
      this.setState({'data': data})
    } else {
      ... fetch file ... concat file ... doesn't update the state
    }
    ... and more calculations
    this.setState({...})
}

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

onFormSubmit - это функция со стрелкой, ее нельзя привязать, если она не перенесена в ES5, и полагаться на это было бы ошибкой.

Быстрое и грязное исправление - сделать ее обычной функцией:

export async function onFormSubmit (files,props) {
    this.setState(...
}

Может быть неловко полагаться на динамический this в этой ситуации, на данный момент это не лучше, чем передача this в качестве аргумента.

Поскольку цельэтой функции является обновление состояния, более чистый способ - сделать его состоянием updater factory:

export const onFormSubmit = (props) => prevState => {
  const { files } = prevState;
  return { /* new state */ };
}

, который можно использовать как:

this.setState(onFormSubmit(this.props));

files доступно на prevState.Использование this.state вместе с setState является антипаттерном, поскольку setState является асинхронным, это может привести к условиям гонки.

Или сделать его не ответственным за обновление состояния, если оно асинхронное, например, оно возвращает обещание:

const newStateObj = await onFormSubmit(this.state.files, this.props);
this.setState(newStateObj);

Если это синхронно, использование this.state не будет хорошей идеей по причине, указанной выше.

0 голосов
/ 03 декабря 2018

Call bind ДО вызова функции примерно так:

onFormSubmit.bind(this)(this.state.files, this.props)
...