【问题标题】:Update state of a class in a recursive function in React在 React 中的递归函数中更新类的状态
【发布时间】:2021-05-20 10:38:36
【问题描述】:

我对 reactjs 很陌生。目前,我正在开发一个需要迭代读取一些文件的项目。所以我将一些文件传递给 fileHandlingFunction

export class MainComponent extends React.Component {
  constructor(){
    this.state = {
      imageFiles: [];
    }
  }

  fileHandlingFunction(files){ // files is an array of image files
    // iterate through the files and append them into an array in state
    this.syncIterate(files, this.syncIterate);
  }

  syncIterate(fileArray, callBackSyncIterate) {
    let tempFile = fileArray[0];
    const reader = new FileReader();
    reader.readAsDataURL(tempFile);
    reader.onload = (event) => {
      this.setState({imageFiles: this.state.imageFiles.concat[reader.result]});
    }

    if (fileArray.length > 1) {
      // Removes the first element of the file array
      let updatedArray = fileArray.slice(1);
      callBackSyncIterate(updatedArray, callBackSyncIterate);
    }
  }
}

当我使用 for 循环将文件附加到状态时,先附加较小的文件,然后附加较大的文件(我严格需要避免这种情况)。这就是使用回调函数以递归方式遍历传递给 fileHandlingFunctionfiles 数组的原因。

但是当我尝试在递归函数调用中插入图像文件时,我得到 “Uncaught TypeError: Cannot read property 'setState' of undefined” 错误。 在这个阶段,我们不能在递归函数调用中改变组件的状态。我希望您提出解决此问题的建议。 我非常感谢您为解决此问题所提供的帮助。提前致谢。

【问题讨论】:

  • 我认为问题在于您的函数将 this 读取为未定义。所以要将函数转换为箭头函数。
  • @PriyankKachhela 我用箭头函数试过了。但后来我又遇到了同样的问题。首先附加较小的文件,然后附加较大的文件。

标签: javascript reactjs react-native


【解决方案1】:

调用方法进入onload:

function fileHandlingFunction(files) { // files is an array of image files
    // iterate through the files and append them into an array in state
    let stateArray = [];
    this.syncIterate(files, stateArray, this.syncIterate);
    this.setState({imageFiles: stateArray});
}

function syncIterate(fileArray, stateArray, callBackSyncIterate) {
    let tempFile = fileArray[0];
    const reader = new FileReader();
    reader.readAsDataURL(tempFile);
    reader.onload = (event) => {
        stateArray.push(reader.result);
        if (fileArray.length > 1) {
            // Removes the first element of the file array
            let updatedArray = fileArray.slice(1);
            callBackSyncIterate(updatedArray, callBackSyncIterate);
        }
    }
}

【讨论】:

  • 在这里,当更新状态作为javascript的异步行为时,stateArray将为空。同时,在 stateArray 中,小文件会先附加,大文件会后附加,原因相同。当 FileReader 读取大文件时,会运行以下代码。
  • 如果在推送后将 if (fileArray.length > 1) 移到 onLoad 中会怎样?这样我认为只有在数据加载到数组后才会再次调用该函数(但可能会花费更多时间)
  • 是的,它奏效了。非常感谢您的热心帮助。
【解决方案2】:

reader.onLoad 为函数本身创建一个新的 javascript 上下文(因此使用了箭头函数)。 因此,您使用的 onload 函数中的“this”仅连接到函数上下文。 尝试添加一个变量来存储类/组件的上下文。 例如let that = this

export class MainComponent extends React.Component {
  constructor(){
    this.state = {
      imageFiles: [];
    }
  }

  fileHandlingFunction(files){ // files is an array of image files
    // iterate through the files and append them into an array in state
    this.syncIterate(files, this.syncIterate);
  }

  syncIterate(fileArray, callBackSyncIterate) {
    let that = this;
    let tempFile = fileArray[0];
    const reader = new FileReader();
    reader.readAsDataURL(tempFile);
    reader.onload = (event) => {
      that.setState({imageFiles: that.state.imageFiles.concat[reader.result]});
    }

    if (fileArray.length > 1) {
      // Removes the first element of the file array
      let updatedArray = fileArray.slice(1);
      callBackSyncIterate(updatedArray, callBackSyncIterate);
    }
  }
}

【讨论】:

    猜你喜欢
    • 2020-10-27
    • 2020-08-15
    • 1970-01-01
    • 2022-11-12
    • 2021-06-26
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    相关资源
    最近更新 更多