jstrother
jstrother

Reputation: 358

Wrong information passed along in Svelte component

I'm building an app that let's you find breweries & brewpubs near you. When that data comes back from the db, it presents about 7 options for you to look at and, when you click on one, it gives you a google map of where it's at so you can go to the Winchester, have a nice cold pint, and wait for this all to blow over.

However, the map is only giving the address of the last location in the list, regardless of which one you click on. :(

BreweryList.svelte

<script>
  import Brewery from '../Beer/Brewery.svelte';
  import { city, breweryList } from '../../Stores/breweryStore';
  // city is a writable store variable and breweryList is an async fetch function
</script>

<h3 class="place-self-center">Brewery List</h3>
<div class="flex flex-wrap justify-center">
  {#await breweryList($city)}
    <p>Finding local breweries...</p>
  {:then list}
    {#each list as brewery (brewery.id)}
      {#if brewery.brewery_type !== 'planning'}
        <Brewery {brewery} />
      {/if}
    {/each}
  {:catch}
    <p>Sorry, something happened. Please try again.</p>
  {/await}
</div>

Brewery.svelte

<script>
  import { showMap, brewLocation } from '../../Stores/directionStore';
  // both showMap and brewLocation are writable store variables
  export let brewery;

  const { name, street, city, state, website_url } = brewery;

  // location is constructed as below to pass on to google maps properly
  const location = `${street.replaceAll(' ', '+')}+${city}+${state}`;

  function setLocation(loc) {
    console.log(loc);
    brewLocation.set(loc);
  }

  function show() {
    showMap.set(true);
  }
</script>

<div class="flex flex-col border-2 m-1.5 p-1.5 max-w-sm">
  <h3>{name}</h3>
  <p>{street}</p>
  <p>{city}, {state}</p>
  <div class="flex flex-col max-w-full">
    <br/>
    {#if website_url}
      <a class="place-self-center underline" href={website_url} target="_blank">Website</a>
      <br/>
    {/if}
    <p class="place-self-center cursor-pointer" on:click="{show}" on:click="{setLocation(location)}">Click for Map</p>
  </div>  
</div>

Can anybody see what I need to fix to get it to work right?

Edit: Here is a REPL detailing the basics of what I was trying to do by setting one store value to a constructed string and another to a Boolean, and both in two separate on:click events. I even have the clickable element as a <p> tag instead of <button> and it works as I would expect. Store Testing REPL

Upvotes: 1

Views: 102

Answers (1)

Stephane Vanraes
Stephane Vanraes

Reputation: 16411

In Brewery.svelte you have the line

<p class="...." on:click="{setLocation(location)}">Click for Map</p>

What is happening is that during the render, Svelte will attach the function defined in the on:click as a listener to this element. In your case however, you do not have a function, but a function call instead. So what is being stored is the result of this function call.

The correct notation would be

on:click="{() => setLocation(location)}"

note that it could be valid to do as you did:

<script>
  function functionGenerator() {
    return function() {
      // actual function
    }
  }
</script>

<button on:click={functionGenerator()}">button</button>

altough the value of doing so is disputable :)

(also note that this should probably be a button element and not a p)

Upvotes: 2

Related Questions