使用扩展运算符避免 React 函数中的状态改变
Using spread operator to avoid mutating state in React function
在我的 React 项目中,我在基于 class 的组件中有一个函数可以处理视频上传。它正在按预期和期望工作。然而,我在检查后意识到它违反了 React 的 don't mutate state mandate。我认为是这样,但我想确保这是真的,而且我想出的解决方案可以解决这个问题。
这是我的组件状态:
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;
}
注意我现在在函数的顶部使用展开运算符。我的问题是:这是否有效地解决了避免状态突变的问题?
是的,您避免了变异状态。但是,您这样做是完全没有必要的,因为如果您不使用该对象,则无需将状态复制到新对象中。
而不是:
newState.uploadFailed = true;
this.setState( { uploadFailed: newState.uploadFailed });
你可以简单地做:
this.setState({ uploadFailed: false });
首先你的代码没有问题。
在我的 React 项目中,我在基于 class 的组件中有一个函数可以处理视频上传。它正在按预期和期望工作。然而,我在检查后意识到它违反了 React 的 don't mutate state mandate。我认为是这样,但我想确保这是真的,而且我想出的解决方案可以解决这个问题。
这是我的组件状态:
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;
}
注意我现在在函数的顶部使用展开运算符。我的问题是:这是否有效地解决了避免状态突变的问题?
是的,您避免了变异状态。但是,您这样做是完全没有必要的,因为如果您不使用该对象,则无需将状态复制到新对象中。
而不是:
newState.uploadFailed = true;
this.setState( { uploadFailed: newState.uploadFailed });
你可以简单地做:
this.setState({ uploadFailed: false });
首先你的代码没有问题。