Reputation:
I have a function component in React called Spec
which has a list of Blocks with the below interface. Spec
maintains a list of blocks that users an add to, edit, or delete.
Issue: The delete action is not working as intended.
console.log()
in the function returns an empty array (it should be length 1), and the second console.log()
returns an array of length 1 (it should be empty)index
I delete, the final (n-1)
elements of the array are deletedCan anyone see what I'm doing wrong?
//types.d.ts
interface Block extends Array {
type: string,
block: StoryBlock | MarkdownBlock
}
interface StoryBlock {
title: string,
description: string,
visibility: boolean,
status: string,
}
interface MarkdownBlock {
title: string,
description: string,
visibility: boolean,
}
const Spec: React.FC<OptSpecProps> = (props) => {
const [blocks, setBlocks] = useState<Block[]>([]);
...
const addBlock = (type: string) => {
let blockSeed;
switch (type) {
case "story":
blockSeed = emptyStoryData;
break;
case "markdown":
blockSeed = emptyMarkdownText
break;
default:
blockSeed = emptyMarkdownText
break;
}
const newBlockArray = blocks.concat({type: type, block: blockSeed})
setBlocks([...newBlockArray]);
};
const removeBlock = (index: number) => {
console.log(blocks) //This logs an empty array
const newBlockArray = blocks.splice(index, 1);
console.log(newBlockArray) // this logs the correct array
setBlocks([...newBlockArray])
}
const updateBlock = (index: number, type: string, block: StoryBlock | MarkdownBlock) => {
let newBlockArray: Block[] = blocks;
newBlockArray[index] = {type: type, block: block};
newBlockArray.forEach((block_itr: Block, i: number) => {
if (i === index) {
block_itr.block = block
block_itr.block.visibility = true
} else {
block_itr.block.visibility = false
}
})
setBlocks([...newBlockArray]);
};
Here is a link to a simplified component sandbox, but it looks from the comments we've identified the issue
Upvotes: 0
Views: 1108
Reputation: 635
You are setting the new block to the result of the splice()
method, although, that method mutates the array in place and returns the removed elements.
Instead, you should clone the array and then splice it
const removeBlock = (index: number) => {
const newBlockArray = [...blocks];
newBlockArray.splice(index, 1);
setBlocks(newBlockArray)
}
P.S. Be aware that the above performs a shallow copy of the array, but it should not be a problem in this case.
Upvotes: 1