S
SolidJS12mo ago
ivan

I have no clue what I am doing wrong

Hello, I am very new to Solid, I am working with stores right now to represent this data structure:
const question = {
title: String,
id: number,
sub_questions: question[]
}
const question = {
title: String,
id: number,
sub_questions: question[]
}
I am using a store to store an array of these questions, and have an App component that renders them
function App() {
const default_question =
{ title: "question", id: 0, sub_questions: []}

const [questions, setQuestions]=createStore([default_question]);
return <>
<ol>
<For each={questions} fallback={<div>No questions saved</div>}>

{(question,i) => {
return <li>
<input
type="text"
value={question.title}
onInput={e => setQuestions(i(),"title",e.target.value)}
/>

<For each={question.sub_questions} fallback=<p>no subquestions</p>>
{(sub_question, j) => {
return (
<input
type="text"
value={sub_question.title}
onInput={e => setQuestions(i(), "sub_questions", j(), "title", e.target.value)}
/>
)
}}
</For>
<button onClick={_ => setQuestions(0,"sub_questions",q=>[...q,{title:"s",id:0,sub_questions:[]}])}>
add sub question to question #{i()+1}
</button>
</li>
}}
</For>
</ol>
<button onClick={_ => setQuestions((questions) => [...questions, default_question])}>
add question
</button>
</>
}
function App() {
const default_question =
{ title: "question", id: 0, sub_questions: []}

const [questions, setQuestions]=createStore([default_question]);
return <>
<ol>
<For each={questions} fallback={<div>No questions saved</div>}>

{(question,i) => {
return <li>
<input
type="text"
value={question.title}
onInput={e => setQuestions(i(),"title",e.target.value)}
/>

<For each={question.sub_questions} fallback=<p>no subquestions</p>>
{(sub_question, j) => {
return (
<input
type="text"
value={sub_question.title}
onInput={e => setQuestions(i(), "sub_questions", j(), "title", e.target.value)}
/>
)
}}
</For>
<button onClick={_ => setQuestions(0,"sub_questions",q=>[...q,{title:"s",id:0,sub_questions:[]}])}>
add sub question to question #{i()+1}
</button>
</li>
}}
</For>
</ol>
<button onClick={_ => setQuestions((questions) => [...questions, default_question])}>
add question
</button>
</>
}
I have no idea why, but each update I add a sub_question via the onlclick setQuestions, it updates the whole store to have the same values for each question in the question array, I have not found a way around this/why it is happenings, pls help. I have tried using a fixed index 0 for the setQuestions function, but this way still updates ALL the questions in the array each time i add a sub question to the fist item in the array. pls help
20 Replies
Brendonovich
Brendonovich12mo ago
can you make a reproduction in the playground?
ivan
ivanOP12mo ago
how do I do that, never used playground before
Brendonovich
Brendonovich12mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Brendonovich
Brendonovich12mo ago
take the code u have and make it produce the same problem in there
ivan
ivanOP12mo ago
ok
Brendonovich
Brendonovich12mo ago
though one thing already stands out - you're reusing default_question it's possible that since you're reusing it, adding a sub question is adding it to that single question instance which is used for all the elements of the array instead prefer to have a makeDefaultQuestion function that returns a new object each time
ivan
ivanOP12mo ago
will try i did the playground thing btw, do you want me to send it as a link or smth
Brendonovich
Brendonovich12mo ago
yeah plz
ivan
ivanOP12mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Brendonovich
Brendonovich12mo ago
as a general rule if you can reproduce your issue in playground/stackblitz you'll be much more likely that someone will a) want to help and b) be able to fix your problem
ivan
ivanOP12mo ago
thanks for the advice
Brendonovich
Brendonovich12mo ago
also you're using 0 instead of i()
No description
ivan
ivanOP12mo ago
Yeah, anyways the issue got fixed by just making default_question a function, but I have no clue why that was causing a problem, can you explain it to me please?
Brendonovich
Brendonovich12mo ago
when you create default_question as a single object, that same object is reused for all the entries of that array, so even though you may have 5 questions, they all actually point to the same object and so updating one updates all of them using the function instead creates a new object instance each time, so each entry of the questions array is unique
ivan
ivanOP12mo ago
damn so under the hood Javascript just points to one shared memory adress where default_question is read instead of cloning it into seperate memory locations, that kinda sucks. well everything makes sense now thanks for your help.
Brendonovich
Brendonovich12mo ago
yep, you have to explicitly clone the object using { ...default_question } (which is only a shallow clone) or do a deep clone or just construct a whole new object
Brendonovich
Brendonovich12mo ago
btw you can make your life a bit easier and do this
No description
Brendonovich
Brendonovich12mo ago
instead of doing setQuestions(i(), "title", ...) you can get a setter for that specific question and call setQuestion("title", ...)
Brendonovich
Brendonovich12mo ago
same goes for sub questions or any other objects in a store
No description
ELSamu
ELSamu11mo ago
setStore supports paths
No description

Did you find this page helpful?