首页 > 解决方案 > React,调用一个无状态函数来组织代码,但是这个怎么绑定呢?

问题描述

鉴于此反应代码

<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
}

当我在 onFormSubmit 函数中时,我看到我丢失了“this”,因此我无法执行例如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
}

选项 Bthis ,作为变量传递

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({...})
}

标签: javascriptreactjsthisbind

解决方案


onFormSubmit是一个箭头函数,它不能被绑定,除非它被转译为 ES5,并且依赖它会是一个错误。

一个快速而肮脏的解决方法是使其成为常规功能:

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

在这种情况下依赖动态可能会很尴尬this,在这一点上,它并不比this作为参数传递更好。

由于此函数的目的是更新状态,因此更简洁的方法是使其成为状态更新器工厂:

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

可以像这样使用:

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

files上可用prevStatethis.state与 with 一起使用是setState一种反模式,因为setState它是异步的,这可能会导致竞争条件。

或者让它不负责更新状态,如果它是异步的,例如它返回一个承诺:

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

如果它是同步的,this.state由于上面提到的原因,使用不会是一个好主意。


推荐阅读