Any way to redo this logic without an infinite loop?

I have a page where I'm getting data from a createAsync and then dynamically rendering this in a <Show/>, however, to get the data to get guaranteed instead of possibly undefined I have to use the render prop, which goes into an issue shown here: https://github.com/solidjs/solid/issues/1149. Essentially I cannot use a <For/> loop inside this, as I get an infinite loop - I have to use an <Index/> loop. Is there some other way to do this pattern or am I basically stuck using <Index/>? To be clear, the issue seems to be in the same component. If I have a child component that uses a <For/> it doesn't seem to cause an infinite loop. Is the only solution other than exclusively using an Index making a page component that is independent of the route?
GitHub
Issues · solidjs/solid
A declarative, efficient, and flexible JavaScript library for building user interfaces. - Issues · solidjs/solid
No description
15 Replies
quinnvaughn
quinnvaughnOP2mo ago
To be clear on the last part of the question, I meant something like
type DataType = { id: number; name: string };

const DataList = (props: { data: DataType[] }) => (
<For each={props.data}>
{(item) => <div>{item.name}</div>}
</For>
);

const App = () => {
const [data] = createResource<DataType[]>(async () => {
const response = await fetch("/api/data");
return response.json();
});

return (
<Show when={data()} fallback={<p>Loading...</p>}>
{(data) => <DataList data={data} />}
</Show>
);
};
type DataType = { id: number; name: string };

const DataList = (props: { data: DataType[] }) => (
<For each={props.data}>
{(item) => <div>{item.name}</div>}
</For>
);

const App = () => {
const [data] = createResource<DataType[]>(async () => {
const response = await fetch("/api/data");
return response.json();
});

return (
<Show when={data()} fallback={<p>Loading...</p>}>
{(data) => <DataList data={data} />}
</Show>
);
};
I'd rather not do that if I don't have to and just keep the page inside the route. (this is ChatGPT code it's not actually the code I have - I'm using createAsync not createResource)
REEEEE
REEEEE2mo ago
It should work fine I think. Do you have code example of what your code looks like now? I can't tell what the issue is from the description
quinnvaughn
quinnvaughnOP2mo ago
Basically if I have a for loop directly inside the Show render prop component (as opposed to inside it but in another component) I'm getting infinite loops, and only the <Index/> is working. Could that be a different issue, like what I'm actually looping over?
quinnvaughn
quinnvaughnOP2mo ago
So take this one, which is inside the <Show/>, I had to switch it from a <For/> because it was basically crashing.
No description
peerreynders
peerreynders2mo ago
Perhaps something else is going on. This doesn't cause an infinite loop:
// file: src/routes/about.tsx
import { For, Show } from 'solid-js';
import { createAsync } from '@solidjs/router';
import { Title } from '@solidjs/meta';

type DataType = { id: number; name: string };

async function getData() {
'use server';
await new Promise((resolve) => setTimeout(resolve, 300));

return [
{ id: 0, name: 'zero' },
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
}

export default function About() {
const data = createAsync(getData);

return (
<main>
<Title>About</Title>
<h1>About</h1>
<Show when={data()}>
{(items) => (
<For each={items()}>{(item) => <div>{item.name}</div>}</For>
)}
</Show>
</main>
);
}
// file: src/routes/about.tsx
import { For, Show } from 'solid-js';
import { createAsync } from '@solidjs/router';
import { Title } from '@solidjs/meta';

type DataType = { id: number; name: string };

async function getData() {
'use server';
await new Promise((resolve) => setTimeout(resolve, 300));

return [
{ id: 0, name: 'zero' },
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
}

export default function About() {
const data = createAsync(getData);

return (
<main>
<Title>About</Title>
<h1>About</h1>
<Show when={data()}>
{(items) => (
<For each={items()}>{(item) => <div>{item.name}</div>}</For>
)}
</Show>
</main>
);
}
quinnvaughn
quinnvaughnOP2mo ago
Certainly possible. This is a relatively complex form page and I can try removing some things and give some updates. It could also be a @felte/solid issue, I don't want to rule that out.
REEEEE
REEEEE2mo ago
Oh it's definitely a felte thing I had this issue in a project use data('propertyName') instead of data().propertyName same thing with errors
quinnvaughn
quinnvaughnOP2mo ago
I'll test this out and let you know, thanks. Still do find it generally easier to work with than modular forms though, I really hated getValues() returning possibly undefined values and having to use a render prop component everywhere
quinnvaughn
quinnvaughnOP2mo ago
I'm now getting this issue with a very minimal version of this page and I'm guessing it's a felte issue but I'm not sure? Here's my code:
quinnvaughn
quinnvaughnOP2mo ago
Typing into an input removes every scenario, but none of the createEffects call or anything. I'm using data('string') like you suggested with a For but the full code was still giving an input loop any time I edited the data (typed into an input, added to the array) The name field is the thing that breaks it, but I don't really get why. And <Index /> works fine with it.
REEEEE
REEEEE2mo ago
Yeah I think I also ended up using Index to solve it
quinnvaughn
quinnvaughnOP2mo ago
Well it's definitely a Felte issue I tried a store No issues Any other good form libraries I could try then? I didn't really like the DX of modular forms because it made it inconvenient to have nested form elements
REEEEE
REEEEE2mo ago
I think there's tanstack form
quinnvaughn
quinnvaughnOP2mo ago
I'm having another weird reactivity issue - I can basically only get my TextField to be clickable on an HMR, I'm unable to click on it to type or whatever. This doesn't happen on just a normal <input /> Here's the code for the TextField and a short video showing what is happening.
quinnvaughn
quinnvaughnOP2mo ago
I've narrowed it down specifically to the onInput call Ok figured this out. It was unrelated to this - I made my own form library kind of disastified with the other ones and I had a get value() and changing it to value: getValueByPath(values(), fieldPath) ?? "", solved the isuse. It worked fine with just a plain signal and whatnot.

Did you find this page helpful?