I'm implementing the history component in svelte. It needs to show when the bids array got udpated,
const bidsArray = [
{ player: 0, bidType: 'pass' },
{ player: 1, bidType: 'level', level: '1', suit: 'NT' },
{ player: 0, bidType: 'level', level: '2', suit: 'NT' },
{ player: 1, bidType: 'level', level: '3', suit: 'S' },
{ player: 0, bidType: 'double' },
{ player: 1, bidType: 'pass' },
];
let bidMap = new Map()
let bids = [];
// Ensure both players are in bidMap from the beginning
for (let i = 0; i < players.length; i++) {
const playerIndex = i;
bidMap.set(playerIndex, []);
}
$: {
bids.forEach((bid) => {
const { player } = bid;
if (!bidMap.has(player)) {
bidMap.set(player, []);
}
if (player !== dealer && bidMap.get(player).length === 0) {
// Add an empty object if the player is not the dealer and the array is empty
bidMap.get(player).push({});
}
bidMap.get(player).push(bid);
});
}
function addBid() {
console.log("bid called");
// Check if there are bids in bidsArray
if (bidsArray.length > 0) {
// Pop the last element from bidsArray
const newBid = bidsArray.pop();
// Update bids using a temporary variable
bids = [...bids, { ...newBid }];
bids = bids
} else {
console.log("No more bids in bidsArray");
}
}
here is my codespace, https://codesandbox.io/p/sandbox/nervous-platform-9hwz5v?file=%2FButton.svelte%3A73%2C15
this is my html code for rendering
<div class="grid-container">
{#each players as player, playerIndex}
{#if bidMap.has(playerIndex)}
<div class="bid-container">
<div class="player-nickname">{player.nickname}</div>
{#each bidMap.get(playerIndex) as bid}
<div
style="visibility: {getBidText(bid) == null ? 'hidden' : 'auto'}"
class="bid-text"
>{getBidText(bid)}</div>
{/each}
</div>
{/if}
{/each}
</div>
If I click the addBid(), it is not updating the bids
array and also the bidMap
.
How to make it re-render, when the bids array updates.
The reason why the re-rendering was not triggered is that Svelte's reactivity is triggered by assignments, and you tried to modify the bidMap by pushing a new item to the Map, which will not cause any update.
To make it re-render, you can simply re-assign value to the variable, in your case, the bidMap
.
<script>
...
$: {
bids.forEach((bid) => {
const { player } = bid;
if (!bidMap.has(player)) bidMap.set(player, []);
if (player !== dealer && bidMap.get(player).length === 0) bidMap.get(player).push({});
bidMap.get(player).push(bid);
bidMap = bidMap // <- Re-assign the outer "bidMap" to the "bidMap" you just pushed to.
});
}
...
</script>
Now you should be able to see the DOM updates.