0

I've just started learning svelte in the last hour so forgive me if this question is stupid or already answered. I tried searching but I don't even know the parlance to ask the question well.

Based on this svelte.dev tutorial link on spread props, my question is as follows.

How do I modify this to be something like this code.

<script>
    import Info from './Info.svelte';

    const pkg = {
                name: 'svelte',
                version: 3,
                speed: 'blazing',
                website: 'https://svelte.dev',

                // this is the modification
                npm: 'https://www.npmjs.com/package/' + {name},

                // I've also tried:
                npm: 'https://www.npmjs.com/package/{name}',
    };
</script>

<Info {...pkg}/>

This is the other modified file.

<script>
    export let name;
    export let version;
    export let speed;
    export let website;
    export let npm;
</script>

<p>
    The <code>{name}</code> package is {speed} fast.
    Download version {version} from <a href={npm}>npm</a>
    and <a href={website}>learn more here</a>
</p>

I'm trying to use a prop in the declaration of another prop exported from the same component.

Seems like it's easy but I'm missing something.

**** Edit *****

Based on Thomas Hennes answer I realized I had the foundation of the question wrong. What I needed to understand was the control flow structure of Svelte, which rendered this formulation redundant. I had a flawed model of a component as some sort of function that took inputs and could also return outputs that could be used in other components. But I'm starting to understand (I think) that it's more just a top-down inheritance model maybe.

TL:DR, Konrads answer was technically correct based on my actual question, but Thomas Hennes answer helped me the most.

JesseRigon
  • 21
  • 7
  • Does this answer your question? [Self-references in object literals / initializers](https://stackoverflow.com/questions/4616202/self-references-in-object-literals-initializers) – Konrad Jan 05 '23 at 20:48
  • @Konrad Yes and no. It's obvious from the answers that it cannot be declared this way from within the object literal declaration, but it doesn't help in trying to get this to work in the context of svelte. What I did for this specific example was to concat {npm}{name} to get the desired result from within the nested component. But I can see scenarios where this wouldn't be helpful. – JesseRigon Jan 05 '23 at 21:10

3 Answers3

2

Jumping in a little late, but here is my take on your problem and what I feel is a more Svelte-like solution.

npm here is really nothing more than a value statically and systematically derived from name, and as such I feel it is redundant data, meaning that it is not essential that this value should be passed as a prop to child components as those child components could just as easily derive that information from the value of name (which is essential data).

On top of that, Svelte's reactive notation is ideally suited to address such needs.

Here is how I would piece it together:

<script>
    import Info from './Info.svelte';

    const pkg = {
                name: 'svelte',
                version: 3,
                speed: 'blazing',
                website: 'https://svelte.dev',
                // none of this is needed, redundant info
                // npm: 'https://www.npmjs.com/package/' + {name},
                // npm: 'https://www.npmjs.com/package/{name}',
    };
</script>

<Info {...pkg}/>

And in Info.svelte:

<script>
    export let name;
    export let version;
    export let speed;
    export let website;
    
    // Reactive code, npm will update whenever name changes
    $: npm = `https://www.npmjs.com/package/${name}`
</script>

<p>
    The <code>{name}</code> package is {speed} fast.
    Download version {version} from <a href={npm}>npm</a>
    and <a href={website}>learn more here</a>
</p>

In general, if you find one prop can/should be derived from another existing prop, then that derived prop is redundant and should not be passed as a prop but instead derived as needed in the component(s) that consume the prop.

Thomas Hennes
  • 9,023
  • 3
  • 27
  • 36
  • This really clears it up for me. Konrads answer was also correct obviously, but you are right in stating this is more sveltish. Konrads answer treated the solution as if it was only an object literal problem, but your answer was more control flow design based which was really the heart of the question. Which admittadly, I don't think I did a good job of explaining. And since Konrad answered what I actually asked instead of what I wanted to know I should keep it as the accepted answer – JesseRigon Jan 06 '23 at 05:16
  • Last comment that might help other newbies as dumb as me. The tuts only showed reactive elements used within the same document, and it somehow didn't hit my smooth brain that of course you could use reactive elements within components where the variables aren't defined yet cause at the end of the day the browser sees it as one document. – JesseRigon Jan 06 '23 at 05:31
  • Oh no you are absolutely right, not only did Konrad answer your question as it was formulated, but his answer is actually useful. I just wanted to add to the debate by pointing out the flaw in the design decision (i.e passing redundant data) and I am glad this is how you understood my answer. Also, do not beat yourself up, you should actually be commended for going beyond blindingly following the tutorial, instead attempting changes and experimenting on your own! Good luck with the learning journey, I hope you enjoy it :) – Thomas Hennes Jan 06 '23 at 22:55
0

After A lot of head scratching.... I finally understand what you want to do.

name is a property of the object pkg, just writing name means you're calling an undeclared variable called name.

However, calling the name property inside the pkg object will also not work, you'll get an call before initialization error.

Instead you can turn the npm property into a function that can access the pkg object properties and return them. Remember you'll call npm as npm() in Info.svelte now because its a function. Please see my example here. Also, do consider learning more about data types in JavaScript...

Happy coding

  • Yes, I did not know that the object doesn't get fully initialized, so that variables could be called, until the object literal has closed. Yes I am new and I am learning about data types in JavaScript as we speak :) – JesseRigon Jan 06 '23 at 05:34
  • Good for you. Glad you got it. All the best on this new learning journey – Natumanya Guy Jan 06 '23 at 09:48
0

Once again, it's explained here Self-references in object literals / initializers

<script>
    import Info from './Info.svelte';

    const pkg = {
                name: 'svelte',
                version: 3,
                speed: 'blazing',
                website: 'https://svelte.dev',
                get npm() { return 'https://www.npmjs.com/package/' + this.name },
                // or
                get npm() { return `https://www.npmjs.com/package/${this.name}` },
    };
</script>

<Info {...pkg}/>

Another solution:

<script>
    import Info from './Info.svelte';

    const name = 'svelte'
    const pkg = {
                name,
                version: 3,
                speed: 'blazing',
                website: 'https://svelte.dev',

                npm: 'https://www.npmjs.com/package/' + name,
                // or
                npm: `https://www.npmjs.com/package/${name}`,
    };
</script>

<Info {...pkg}/>
Konrad
  • 21,590
  • 4
  • 28
  • 64
  • wow thank you. I tried using the getter but I was too dumb to get it working syntactically. Yeah obviously I'm new to svelte and javascript. I didn't realize that you could declare the var in the object and then assign it elsewhere with svelte. Doesn't say that anywhere in the docs but I guess that's just a js thing. Also I learned a new syntax of '' vs `` with using variables within strings. Appreciate the help. – JesseRigon Jan 05 '23 at 22:21