【问题标题】:Using spread operator to avoid mutating state in React function使用扩展运算符避免在 React 函数中改变状态
【发布时间】:2021-03-25 07:45:15
【问题描述】:

在我的 React 项目中,我在基于类的组件中有一个函数来处理视频上传。它按预期和期望工作。然而,经过检查,我意识到它违反了 React 的不改变状态要求。我认为是这样,但我想确保这是真的,并且我想出的解决方案可以解决这个问题。

这是我的组件状态:

  state = {
    streamingRes: {},
    uploadFailed: false
  }

我的初始函数看起来像这样(注意有 3 个地方我正在设置状态):

  fileUploadHandler = (id, file, fileId) => {
    const isValid = this.validateVideoFileType(file);
    if(!isValid) this.props.showError(`${file.name} is of the wrong file type (${file.type}).  File must be an acceptable video format.`);

    let dataStream = io.Stream.createStream();

    io.Socket.on('userVideos.uploadProgress', (data) => {
      this.setState( { streamingRes: data });
      if(fileId === data.data.guid) {
        this.uploadCompletionPercentage = data.data.progress;
      } 
    });

    io.Stream(io.Socket).emit('userVideos.upload', dataStream, {
      guid: fileId,
      size: file.size
    }, (data) => {
      if(data.status === "failure") {
        this.props.onUploadFailed();
        this.setState( { uploadFailed: true })
      }
      else if(data.status === "success") {
        this.props.upload(id)
      }
    });

    this.setState( { uploadFailed: false });

    io.Stream.createBlobReadStream(file).pipe(dataStream);
    return;
  }

为了避免改变状态,我将这个函数更新为如下所示:

  handleFileUpload = (id, file, fileId) => {
    let newState = {...this.state};
    const isValid = this.validateVideoFileType(file);
    if(!isValid) this.props.showError(`${file.name} is of the wrong file type (${file.type}).  File must be an acceptable video format.`);

    let dataStream = io.Stream.createStream();

    io.Socket.on('userVideos.uploadProgress', (data) => {
      this.setState( { streamingRes: data });
      if(fileId === data.data.guid) {
        this.uploadCompletionPercentage = data.data.progress;
      } 
    });

    io.Stream(io.Socket).emit('userVideos.upload', dataStream, {
      guid: fileId,
      size: file.size
    }, (data) => {
      if(data.status === "failure") {
        this.props.onUploadFailed();
        newState.uploadFailed = true;
        this.setState( { uploadFailed: newState.uploadFailed });
      }
      else if(data.status === "success") {
        this.props.upload(id)
      }
    });

    newState.uploadFailed = false;
    this.setState( { uploadFailed: newState.uploadFailed });

    io.Stream.createBlobReadStream(file).pipe(dataStream);
    return;
  }

请注意,我现在在函数顶部使用扩展运算符。我的问题是:这是否有效地解决了避免状态突变的问题?

【问题讨论】:

    标签: reactjs setstate react-state-management


    【解决方案1】:

    是的,你已经避免了变异状态。但是,您这样做是完全没有必要的,因为如果您不使用该对象,则无需将状态复制到新对象中。

    代替:

    newState.uploadFailed = true;
    this.setState( { uploadFailed: newState.uploadFailed });
    

    你可以这样做:

    this.setState({ uploadFailed: false });
    

    一开始你的代码没有问题。

    【讨论】:

    • 所以你是说我最初的实现不是变异状态?
    • @Muirik 一点也不。例如,变异状态是this.state.uploadFailed = false。当您的状态包含对象而不是简单值时,突变状态通常是一个问题,例如如果您尝试在不先复制值的情况下更改 progressResponse
    • @Muirik 如果发现更多问题是this.uploadCompletionPercentage,它显然会在不使用道具状态的情况下以某种方式改变组件。
    • 是的,我现在明白了。这是因为我误解了变异状态问题。我会相应地更新。
    猜你喜欢
    • 2021-12-01
    • 2018-12-09
    • 2020-12-20
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 2020-04-06
    相关资源
    最近更新 更多