How to destructure properly?

Hey community! I'm brand new to SolidJS so I apologize if this is a basic question. I'm trying to find a way to destructure props the SolidJS way. I've tried this a couple of different ways, and I seem to run into problems. My issue stems from a request that returns a bunch of nested data (GraphQL), and I'd like to break that data up into pieces. I'd like to change data that looks like this: data()?.user?.repositoriesContributedTo.nodes
import { destructure } from '@solid-primitives/destructure'

const FC = () => {
const [data] = newQuery<UserReposQuery>(UserQuery, variables); // This has reactivity, and is a response to a request.
const { user: { name, company, repositoriesContributedTo } } = destructure(data, { deep: true }) // I believe using this library maintains reactivity?

return (
<div>
<p>{company()}</p>
<p>{name()}</p>
</div>
)
}
import { destructure } from '@solid-primitives/destructure'

const FC = () => {
const [data] = newQuery<UserReposQuery>(UserQuery, variables); // This has reactivity, and is a response to a request.
const { user: { name, company, repositoriesContributedTo } } = destructure(data, { deep: true }) // I believe using this library maintains reactivity?

return (
<div>
<p>{company()}</p>
<p>{name()}</p>
</div>
)
}
17 Replies
bigmistqke
bigmistqke3mo ago
hi creme 👋 could u elaborate on what's not working as u expected?
CremeDeLaKremlin
Oh sorry, I totally spaced on including the errors I get: Property 'user' does not exist on type 'DeepSpread<ReactiveSource>'
type UserReposQuery = {
__typename?: "Query" | undefined;
user?: {
__typename?: "User" | undefined;
name?: string | null | undefined;
company?: string | null | undefined;
avatarUrl: any;
type UserReposQuery = {
__typename?: "Query" | undefined;
user?: {
__typename?: "User" | undefined;
name?: string | null | undefined;
company?: string | null | undefined;
avatarUrl: any;
bigmistqke
bigmistqke3mo ago
is it only a type-error or does it errors during runtime?
CremeDeLaKremlin
There is one more error in browser: Uncaught TypeError: can't convert undefined to object destructure index.js:39 And this is what I'm passing to destructure: const data: Resource<UserReposQuery | undefined>
bigmistqke
bigmistqke3mo ago
mm ye my interpretation (full disclosure: never used destructure) is that destructure allows for undefined (see https://primitives.solidjs.community/package/destructure#accessing-keys-initially-missing) but only at the leaves
Solid Primitives
A library of high-quality primitives that extend SolidJS reactivity
bigmistqke
bigmistqke3mo ago
const x: {user?: {id: string}} = {}
const {user: {id}} = x
const x: {user?: {id: string}} = {}
const {user: {id}} = x
this would error in regular js too
CremeDeLaKremlin
I really appreciate your responses by the way
bigmistqke
bigmistqke3mo ago
thank u!
CremeDeLaKremlin
Ah yes, I think that error makes sense. Can't we circumvent with:
const x: {user?: {id: string}} = {}
const {user: {id}} = x ?? {}
const x: {user?: {id: string}} = {}
const {user: {id}} = x ?? {}
bigmistqke
bigmistqke3mo ago
the above would still error in js have you looked at reconcile and solid's store?
CremeDeLaKremlin
Gotcha. So what would the solution be? Just destructure user and then access its properties with optional chaining? Would it be bad practice to user destructure again on user? Yes to store, no to reconcile. Though I think my understanding of store is poor
peerreynders
peerreynders3mo ago
I tend to use this approach:
const company = (data: Resource<UserReposQuery>) => data()?.user?.company;
const name = (data: Resource<UserReposQuery>) => data()?.user?.name;

const FC = () => {
const [data] = newQuery<UserReposQuery>(UserQuery, variables); // This has reactivity, and is a response to a request.

return (
<div>
<p>{company(data)}</p>
<p>{name(data)}</p>
</div>
)
}
const company = (data: Resource<UserReposQuery>) => data()?.user?.company;
const name = (data: Resource<UserReposQuery>) => data()?.user?.name;

const FC = () => {
const [data] = newQuery<UserReposQuery>(UserQuery, variables); // This has reactivity, and is a response to a request.

return (
<div>
<p>{company(data)}</p>
<p>{name(data)}</p>
</div>
)
}
bigmistqke
bigmistqke3mo ago
you can do it manually, like peer proposes
CremeDeLaKremlin
Ahhh, that does exactly what I want it to do.
bigmistqke
bigmistqke3mo ago
I would personally just do
const FC = () => {
const [data] = newQuery<UserReposQuery>(UserQuery, variables); // This has reactivity, and is a response to a request.
const name = () => data()?.user?.name

return (
<div>
<p>{name()}</p>
</div>
)
}
const FC = () => {
const [data] = newQuery<UserReposQuery>(UserQuery, variables); // This has reactivity, and is a response to a request.
const name = () => data()?.user?.name

return (
<div>
<p>{name()}</p>
</div>
)
}
but it's the same idea
CremeDeLaKremlin
Yep, will go with the second proposed approach. You guys are awesome. Thanks for answering this, and so fast also.
bigmistqke
bigmistqke3mo ago
the idea of reconcile is to take immutable data (like a response from a fetch) and then diff it and only update the properties that have changed (aka finegrain it) but it might be a bit of a hassle to combine it with createResource appreciate 🙏