Nested Reactivity not working

Hi, i'm trying to figure out why my a particular component (combatdisplay.jsx) of my solidjs project isn't updating when I change a deeply nested property in a store through the deployCard function in my stores class (context.jsx). What's weird is that all the other components in my project that also react to nested properties works without issue, so I am very confused as to why it is not working for this particular component When debugging myself, I found that the backend data updating code looks to be right, as it does update values in the store correctly so I don't believe there's anything wrong with that. Simply put, the component just doesn't react to updated data. I've also rewritten the deployCard functions two different ways (one with and without using produce), but the component still doesn't update. Here is a github repo for all the code https://github.com/maikyonn/card-solid-test
GitHub
GitHub - maikyonn/card-solid-test
Contribute to maikyonn/card-solid-test development by creating an account on GitHub.
8 Replies
amehoshi
amehoshi5mo ago
Here is the code for quick reference
const deployCard = (inputs) => {
const id = inputs[0];
const location = inputs[1];

setGame(
"players",
id,
produce((player) => {
player.combat_board[location].deployed = player.hand.find(
(card) => card.id === player.selected_card_id
);
const index = player.hand.findIndex(
(c) => c.id === player.selected_card_id
);
if (index > -1) {
player.hand.splice(index, 1);
}
player.selected_card_id = undefined;
})
);
};
const deployCard = (inputs) => {
const id = inputs[0];
const location = inputs[1];

setGame(
"players",
id,
produce((player) => {
player.combat_board[location].deployed = player.hand.find(
(card) => card.id === player.selected_card_id
);
const index = player.hand.findIndex(
(c) => c.id === player.selected_card_id
);
if (index > -1) {
player.hand.splice(index, 1);
}
player.selected_card_id = undefined;
})
);
};
import { useGame } from "../data/context";
import { For, createMemo } from "solid-js";

export const CombatDisplay = () => {
const [game, { deployCard }] = useGame();

const currentPlayerIndex = 0;
const currentPlayerCombatBoard = createMemo(() => {
return game.players[currentPlayerIndex].combat_board;
});

return (
<div class="combat-display">
<For each={currentPlayerCombatBoard()}>
{(location) => {
const card = location.deployed;
console.log("rendering");
return (
<div class="card">
<h4>{card ? card.name : "Empty"}</h4>
<p>{location.type}</p>
{card ? (
<button
onClick={[
deployCard,
[currentPlayerIndex, location.location],
]}
>
Action
</button>
) : (
<button
onClick={[
deployCard,
[currentPlayerIndex, location.location],
]}
>
Deploy
</button>
)}
</div>
);
}}
</For>
</div>
);
};
import { useGame } from "../data/context";
import { For, createMemo } from "solid-js";

export const CombatDisplay = () => {
const [game, { deployCard }] = useGame();

const currentPlayerIndex = 0;
const currentPlayerCombatBoard = createMemo(() => {
return game.players[currentPlayerIndex].combat_board;
});

return (
<div class="combat-display">
<For each={currentPlayerCombatBoard()}>
{(location) => {
const card = location.deployed;
console.log("rendering");
return (
<div class="card">
<h4>{card ? card.name : "Empty"}</h4>
<p>{location.type}</p>
{card ? (
<button
onClick={[
deployCard,
[currentPlayerIndex, location.location],
]}
>
Action
</button>
) : (
<button
onClick={[
deployCard,
[currentPlayerIndex, location.location],
]}
>
Deploy
</button>
)}
</div>
);
}}
</For>
</div>
);
};
bigmistqke
bigmistqke5mo ago
bit confused w the code currentPlayerIndex never changes? in the current setup currentPlayerCombatBoard is not going to react on changes of currentPlayerindex, mb that's it? the memo is a bit redundant too in ur code, but it should still work.
amehoshi
amehoshi5mo ago
Yea for now it never changes currentPlayerCombatBoard is supposed to be updated when the .combat_board property is modified by the deployCard function But its not being updated for some reason, even though the store has been for sure updated so like when this line of code runs in the deployCard after an onClick event player.combat_board[location].deployed = player.hand.find( (card) => card.id === player.selected_card_id ); I expect the currentPlayerCombatBoard() to react to that change and rerender its element
bigmistqke
bigmistqke5mo ago
const card = location.deployed; is a bit fishy too will not be reactive if deployed updates a yes
amehoshi
amehoshi5mo ago
lemme see
bigmistqke
bigmistqke5mo ago
maybe try const card = () => location.deployed instead and I would advice to use <Show when={card()} fallback={...}>...</Show> instead of ternaries
amehoshi
amehoshi5mo ago
OMG yes that was it bruh thank you so much for your help @bigmistqke
bigmistqke
bigmistqke5mo ago
ur welcome! <For/> is referential, so it will only run one time per location. even if they would switch order the function will not re-run (only index() will change). <Index/> is per index, so it will only run one time per indice, but there value() would change if something in the array happens.
Want results from more Discord servers?
Add your server
More Posts