S
SolidJSā€¢2y ago
nikivi

How to do nested <For

I have a signal that is array of arrays
const [grid, setGrid] = createSignal([
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 3, 0, 0, 0, 1],
[1, 0, 0, 4, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
])
const [grid, setGrid] = createSignal([
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 3, 0, 0, 0, 1],
[1, 0, 0, 4, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
])
I want to render it out on screen and for solid to update it. However I read https://www.solidjs.com/tutorial/flow_for and still not too sure how to do nested <For. I tried this:
return (
<main class="Main">
<div class="boxWrapper">
<For each={grid()}>
{(row, i) => (
<For each={row}>
<div>{row}</div>
</For>
)}
</For>
</div>
</main>
return (
<main class="Main">
<div class="boxWrapper">
<For each={grid()}>
{(row, i) => (
<For each={row}>
<div>{row}</div>
</For>
)}
</For>
</div>
</main>
But it doesn't work. In react it's quite simple, I just do
return (
<main class="Main">
<div class="boxWrapper">
{grid().map((row) => {
return row.map((box) => {
return <div class="box">{box}</div>
})
})}
</div>
</main>
)
return (
<main class="Main">
<div class="boxWrapper">
{grid().map((row) => {
return row.map((box) => {
return <div class="box">{box}</div>
})
})}
</div>
</main>
)
Thanks for any help.
SolidJS
Solid is a purely reactive library. It was designed from the ground up with a reactive core. It's influenced by reactive principles developed by previous libraries.
38 Replies
nikivi
nikiviā€¢2y ago
return (
<main class="Main">
<div class="boxWrapper">
<For each={grid()}>
{(row, i) => {
return (
<>
<For each={row}>
{(box) => {
return <div class="box">{box}</div>
}}
</For>
</>
)
}}
</For>
</div>
</main>
)
return (
<main class="Main">
<div class="boxWrapper">
<For each={grid()}>
{(row, i) => {
return (
<>
<For each={row}>
{(box) => {
return <div class="box">{box}</div>
}}
</For>
</>
)
}}
</For>
</div>
</main>
)
ok this works I think šŸ¤” I am not sure why the grid is not updating
nikivi
nikiviā€¢2y ago
GitHub
test/snake.tsx at main Ā· nikitavoloboev/test
Trying new things. Contribute to nikitavoloboev/test development by creating an account on GitHub.
nikivi
nikiviā€¢2y ago
GitHub
test/snake.tsx at main Ā· nikitavoloboev/test
Trying new things. Contribute to nikitavoloboev/test development by creating an account on GitHub.
nikivi
nikiviā€¢2y ago
I console logged, the values do change I can't console log inside the component function itself as it only runs once but I thought that if I render it out with jsx it would update
thetarnav
thetarnavā€¢2y ago
imo you should use <Index> for that as the index is what's identifying the input element - not reference because changing 0 to 1 is changing the reference
nikivi
nikiviā€¢2y ago
<Index each={grid()}>
{(row) => {
return (
<>
<Index each={row}>
{(box) => {
return <div class="box">{box}</div>
}}
</Index>
</>
)
}}
</Index>
<Index each={grid()}>
{(row) => {
return (
<>
<Index each={row}>
{(box) => {
return <div class="box">{box}</div>
}}
</Index>
</>
)
}}
</Index>
something like this?
nikivi
nikiviā€¢2y ago
get some type errors
nikivi
nikiviā€¢2y ago
SolidJS
Solid is a purely reactive library. It was designed from the ground up with a reactive core. It's influenced by reactive principles developed by previous libraries.
thetarnav
thetarnavā€¢2y ago
Also, since the two components are to be derived from a single signal - both of them need to be subscribing to it So the nested <Index> should actually reference the signal as well in the each function
nikivi
nikiviā€¢2y ago
reading its docs it seems like its similar to For
thetarnav
thetarnavā€¢2y ago
And thirdly, using a store would probably be the best
nikivi
nikiviā€¢2y ago
I have one component though so I put both snake and grid inside one store why doesn't it work with <For though
const [state, setState] = createStore({
grid: [
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 3, 0, 0, 0, 1],
[1, 0, 0, 4, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
],
snake: [],
})
const [state, setState] = createStore({
grid: [
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 3, 0, 0, 0, 1],
[1, 0, 0, 4, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
],
snake: [],
})
trying it with store
JCM
JCMā€¢2y ago
When you call newSnake, line 155, you supply the same array (although some elements are mutated). The signal doesn't change if it's assigned a value that is equal to the old value (eg. same array) You can opt out of that with the createSignal options
JCM
JCMā€¢2y ago
SolidJS
Solid is a purely reactive library. It was designed from the ground up with a reactive core. It's influenced by reactive principles developed by previous libraries.
nikivi
nikiviā€¢2y ago
then moveSnake(state, setState, direction) I get this I guess
JCM
JCMā€¢2y ago
In my oppinion this has nothing to do with For vs Index
nikivi
nikiviā€¢2y ago
I have Q about this actually
JCM
JCMā€¢2y ago
Using a store would solve the issue
nikivi
nikiviā€¢2y ago
reason I creates those mutable variables is that I can't do setStates there and expect changes to be instant they are not thats quite a big change if I move it to store hope it will solve it
function moveSnake(
state: any,
setState: (state: any) => void),
direction: "up" | "down" | "left" | "right",
) {
function moveSnake(
state: any,
setState: (state: any) => void),
direction: "up" | "down" | "left" | "right",
) {
I not sure how to type store well
JCM
JCMā€¢2y ago
Check if `setSnake([...newSnake]) solves the issue. By cloning the array it should always notify the subscribers
nikivi
nikiviā€¢2y ago
so here
newSnake = [[rowOfHead, indexOfHead], ...snake]
newSnake = [[rowOfHead, indexOfHead], ...snake]
if (snake.length > 0) {
setSnake([[rowOfHead, indexOfHead], ...snake])
} else {
setSnake([[rowOfHead, indexOfHead]])
}
if (snake.length > 0) {
setSnake([[rowOfHead, indexOfHead], ...snake])
} else {
setSnake([[rowOfHead, indexOfHead]])
}
do this?
if (snake.length > 0) {
setSnake([[rowOfHead, indexOfHead], ...snake])
} else {
setSnake([[rowOfHead, indexOfHead]])
}
console.log(snake)
if (snake.length > 0) {
setSnake([[rowOfHead, indexOfHead], ...snake])
} else {
setSnake([[rowOfHead, indexOfHead]])
}
console.log(snake)
that console log there won't be updated value and I need new value of snake later in function or here
setGrid(updatedGrid)
setSnake(newSnake)
setGrid(updatedGrid)
setSnake(newSnake)
you mean should I continue with migration to store or that won't help
thetarnav
thetarnavā€¢2y ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
JCM
JCMā€¢2y ago
You can either create a new top level array with a spread, or alternatively use { equals: false } option on the signal to ensure it the signal fires each time the setter is called, even if it's the same array. The example of @thetarnav creates a copy with slice instead of spread, but it's similar
nikivi
nikiviā€¢2y ago
example of @thetarnav is blowing my mind a bit trying to make sense of it
thetarnav
thetarnavā€¢2y ago
The secret is that I'm always calling grid() in each place it has to track it. Since this is a single signal, and you only reference some property of it without calling it, it won't track the change. Using createStore gives you that each property access is trackable
nikivi
nikiviā€¢2y ago
GitHub
test/box.tsx at main Ā· nikitavoloboev/test
Trying new things. Contribute to nikitavoloboev/test development by creating an account on GitHub.
nikivi
nikiviā€¢2y ago
I am now trying to
thetarnav
thetarnavā€¢2y ago
So no component gets recreated, BUT all the places that call grid() will have to reexecute on each update to check if they don't have to update. So it's diffing, just smart diffing. Using createStore will eliminate that issue as well - you subscribe to a single value directly
nikivi
nikiviā€¢2y ago
move @thetarnav code to use my functions to update without store for now if I can as that would be a big diff so if I get it right it seems I can't pass setters to my function? like my moveSnake in the end it should just update the signal value then DOM should change as signal value is updated im confused why it doesn't šŸ˜ I checked that logic is valid if I just console log updatedGrid and newSnake at end like the grid has right values and all I will try to add things on top of @thetarnav code instead of combining
thetarnav
thetarnavā€¢2y ago
thetarnav
thetarnavā€¢2y ago
those will be the same references
nikivi
nikiviā€¢2y ago
ohh ok but if I don't do it and say do set things instantly how do I get current updated values inside same function
thetarnav
thetarnavā€¢2y ago
const newValue = setSignal(p => ...)
const newValue = setSignal(p => ...)
? But I would just destructure the top-level signal values and apply the change
nikivi
nikiviā€¢2y ago
ok will try thank you like Big Thief too btw šŸ™‚
thetarnav
thetarnavā€¢2y ago
this is the first time I saw a function that takes both value and the setter šŸ˜„
thetarnav
thetarnavā€¢2y ago
I would never pass the setter around
nikivi
nikiviā€¢2y ago
yea it did look ugly I just thought thats how you had to do it like im coming from react that would work in react or well you can actually have the function inside component so you don't need to pass it too
thetarnav
thetarnavā€¢2y ago
I mean I like to have a single place where the state is updated, then it gets confusing where the change actually happens, is it batched or not, idk oh I missed that ā¤ļø ngl I have yours "Inspired" playlist often on repeat
Want results from more Discord servers?
Add your server
More Posts
Is there a way to make an iframe reactively render with state/signals from its parent?Stuff that I tried: - Set state/setState in the iframe.window.someGlobal and access it in the iframehow can I use createEffect so it doesn't rerun when certain signals changemy code: https://github.com/nikitavoloboev/test/blob/main/solid-start/src/routes/snake.tsxForward reference a Component's state in TemplateI try to wrap a Trigger and a Display component in a state managing component like so ``` export fuChild component cannot access context that the parent can access?I have a file like this: ```tsx import { useLexicalComposerContext } from "./LexicalComposerContext"How do I scroll to bottom, on a scrollable content that displays a Show when`<div ref={$content}` `Show when={signal()}` ``` createEffect(() => { set_signal(true) $content.Solid JS force rerender on signal changeI need to force Solid JS to make changes to the DOM every time a signal changes. Currently it seems Generate random numbers serverside and don't regenerate on hydrationI'm trying to generate a list of random numbers for a skeleton loader, and I've found a solution, buHow can we lazy load route data using @solidjs/router ?When using this pattern: ```javascript import UserData from "./pages/users/[id].data.js"; const UseContext In TypescriptI'm trying to create a context in Typescript following this example, but copying and pasting the codVercel + PrismaHopefully someone here can help with my issue, but I'm trying to use Prisma with solid + vercel, how