在 REACT 中复制而不引用状态对象
Copying and not referencing state object in REACT
正在尝试创建状态对象的副本,更改它,然后使用 setState() 对其进行设置。
但是,我无法复制该对象,而是创建了一个引用。这意味着当我编辑它时,我直接编辑状态对象,这意味着 setState() 不会重新呈现,因为从我编辑对象到我尝试 运行 setState().
我已经能够用一个数组来做到这一点,它包含在我下面的代码中。
// This is my state
interface IEditPanelState {
currentFiles: SearchResults;
newFiles: File[];
}
// This is my function
public async cacheFiles(files: File[]) {
// This works
let cachedFiles = [...this.state.newFiles];
// This is creating a reference. How to copy Searchresults??
let currentFiles = this.state.currentFiles;
for(let file of files) {
cachedFiles.push(file);
currentFiles.PrimarySearchResults.push({
Title: file.name
});
}
console.log(currentFiles);
console.log(cachedFiles);
console.log(this.state.newFiles);
this.setState({
newFiles: cachedFiles,
currentFiles: currentFiles
});
}
您能解释一下必须对状态进行深度克隆背后的主要需求吗?如果数组大小增加并且也可能是不必要的,它可能无法执行。
此外,由于您的新状态取决于之前的状态,因此如果您遵循那里的功能约定可能会有所帮助。如下所示
// this has the logic to extract current files from present state
const getCurrentFiles = (currState) => { ... };
const cacheFiles = (files) => {
this.setState((currentState) => {
const currentFiles = getCurrentFiles(currentState);
return ({
newFiles: [...currState.currentFiles, ...files],
currentFiles
});
})
}
Link 至 setState
功能约定的文档 - setState documentation
这已由@SarangPM 作为评论回答。
答案如下:
let currentFiles = this.state.currentFiles;
will always create a reference. For a shallow copy, you can use the spread operator and for a deep clone, you can use deep clone function from lodash.
我安装了 lodash,遇到了一些问题,但最终修复了它。查看下面我的评论。
I just installed it using npm. It says to import using: import { _ } from 'lodash';
However this results in the following error: '_' can only be imported by turning on the 'esModuleInterop' flag and using a default import
. EDIT: nvm, I got it working using: import { cloneDeep } from 'lodash';
非常感谢@SarangPM 回答我的问题并解决了我的问题。
我添加这个作为答案,因为@SarangPM 没有。
正在尝试创建状态对象的副本,更改它,然后使用 setState() 对其进行设置。
但是,我无法复制该对象,而是创建了一个引用。这意味着当我编辑它时,我直接编辑状态对象,这意味着 setState() 不会重新呈现,因为从我编辑对象到我尝试 运行 setState().
我已经能够用一个数组来做到这一点,它包含在我下面的代码中。
// This is my state
interface IEditPanelState {
currentFiles: SearchResults;
newFiles: File[];
}
// This is my function
public async cacheFiles(files: File[]) {
// This works
let cachedFiles = [...this.state.newFiles];
// This is creating a reference. How to copy Searchresults??
let currentFiles = this.state.currentFiles;
for(let file of files) {
cachedFiles.push(file);
currentFiles.PrimarySearchResults.push({
Title: file.name
});
}
console.log(currentFiles);
console.log(cachedFiles);
console.log(this.state.newFiles);
this.setState({
newFiles: cachedFiles,
currentFiles: currentFiles
});
}
您能解释一下必须对状态进行深度克隆背后的主要需求吗?如果数组大小增加并且也可能是不必要的,它可能无法执行。
此外,由于您的新状态取决于之前的状态,因此如果您遵循那里的功能约定可能会有所帮助。如下所示
// this has the logic to extract current files from present state
const getCurrentFiles = (currState) => { ... };
const cacheFiles = (files) => {
this.setState((currentState) => {
const currentFiles = getCurrentFiles(currentState);
return ({
newFiles: [...currState.currentFiles, ...files],
currentFiles
});
})
}
Link 至 setState
功能约定的文档 - setState documentation
这已由@SarangPM 作为评论回答。
答案如下:
let currentFiles = this.state.currentFiles;
will always create a reference. For a shallow copy, you can use the spread operator and for a deep clone, you can use deep clone function from lodash.
我安装了 lodash,遇到了一些问题,但最终修复了它。查看下面我的评论。
I just installed it using npm. It says to import using:
import { _ } from 'lodash';
However this results in the following error:'_' can only be imported by turning on the 'esModuleInterop' flag and using a default import
. EDIT: nvm, I got it working using:import { cloneDeep } from 'lodash';
非常感谢@SarangPM 回答我的问题并解决了我的问题。 我添加这个作为答案,因为@SarangPM 没有。