JavaScript >> Javascript tutorial >  >> Tags >> URL

Caching af data ved hjælp af URL-forespørgselsparametre i JavaScript

Sådan gemmer du midlertidigt data i en URL-forespørgselsparametre og henter dem og parser dem til brug i din brugergrænseflade.

Kom godt i gang

Til denne tutorial skal vi bruge CheatCodes full-stack JavaScript-ramme, Joystick. Joystick samler en frontend UI-ramme med en Node.js-backend til at bygge apps.

Til at begynde med vil vi installere Joystick via NPM. Sørg for, at du bruger Node.js 16+ før installation for at sikre kompatibilitet (læs denne vejledning først, hvis du har brug for at lære, hvordan du installerer Node.js eller kører flere versioner på din computer):

Terminal

npm i -g @joystick.js/cli

Dette vil installere Joystick globalt på din computer. Når det er installeret, lad os derefter oprette et nyt projekt:

Terminal

joystick create app

Efter et par sekunder vil du se en besked logget ud til cd ind i dit nye projekt og kør joystick start . Før du kører joystick start , skal vi installere én pakke, query-string :

Terminal

cd app && npm i query-string

Denne pakke hjælper os med at parse og indstille vores forespørgselsparametre på farten. Når det er installeret, skal du gå videre og starte serveren:

Terminal

joystick start

Herefter skulle din app køre, og vi er klar til at komme i gang.

Tilføjelse af noget global CSS

For bedre at kunne kontekstualisere vores demo, vil vi tilføje CSS gennem hele selvstudiet. For at starte skal vi tilføje noget globalt CSS, der skal håndtere den overordnede visning af vores sider:

/index.css

* {
  margin: 0;
  padding: 0;
}

*, *:before, *:after {
  box-sizing: border-box;
}

body {
  font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
  font-size: 16px;
  background: #fff;
}

.container {
  width: 100%;
  max-width: 800px;
  margin: 15px auto;
  padding: 0 15px !important;
}

@media screen and (min-width: 768px) {
  .container {
    margin-top: 50px;
  }
}

Som standard, når du åbner denne fil, kun CSS for body tag vil eksistere. De specifikke detaljer her betyder ikke så meget, men det, vi gør, er at tilføje nogle "nulstil"-stile for alle HTML-elementer i browseren (fjerne standardbrowserens CSS, der tilføjer ekstra margener og polstring og ændrer, hvordan elementer flyder i boksen model) og en .container klasse, der giver os mulighed for nemt at oprette en centreret <div></div> til indpakning af indhold.

Det er alt, vi har brug for her. Vi tilføjer mere CSS senere på det individuelle komponentniveau. Dernæst skal vi oprette en rute til en dummy-side, som vi skal bruge til at teste vores forespørgselsparametre.

Tilføjelse af en rute, der skal omdirigeres til for at teste parametre

I en Joystick-app er alle ruter defineret på serveren ét sted:/index.server.js . Lad os åbne det nu og tilføje en rute til en dummy-side, som vi kan omdirigere til og bekræfte, at vores forespørgselsparametre fungerer som forventet:

/index.server.js

import node from "@joystick.js/node";
import api from "./api";

node.app({
  api,
  routes: {
    "/": (req, res) => {
      res.render("ui/pages/index/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "/listings/:listingId": (req, res) => {
      res.render("ui/pages/listing/index.js");
    },
    "*": (req, res) => {
      res.render("ui/pages/error/index.js", {
        layout: "ui/layouts/app/index.js",
        props: {
          statusCode: 404,
        },
      });
    },
  },
});

Da du kørte joystick start tidligere fra roden af ​​din app, er dette den fil, som Joystick startede op. Her er node.app() funktionen starter en ny Node.js-applikation ved hjælp af Express.js bag kulisserne. Til Express, routes objekt, der defineres på indstillingsobjektet, der sendes til node.app() er afleveret.

Som standard på dette objekt ser vi / og * ruter bliver defineret. Ovenfor har vi tilføjet en ny rute /listings/:listingId . Til vores app bygger vi en falsk ejendomssøgnings-UI, hvor brugere vil være i stand til at tilpasse nogle søgeparametre og se fortegnelser.

Her opretter vi ruten for en falsk - den vil ikke indlæse nogen reelle data, kun nogle statiske dummy-data - listeside, som brugeren vil være i stand til at omdirigere til. Ideen er, at vi sætter nogle forespørgselsparametre på URL'en på / (indeks) rute og derefter tillade brugeren at klikke på et link til denne /listings/:listingId side. Når de gør det, vil de forespørgselsparametre, vi indstiller, "gå væk." Når de går tilbage, forventer vi, at disse forespørgselsparametre gendannes.

Inde på ruten her kalder vi til en funktion på res objekt, res.render() som er en speciel funktion, som Joystick tilføjer til standard Express res objekt. Denne funktion er designet til at tage vejen til en Joystick-komponent i vores app og gengive den på siden.

Her antager vi, at vi har en side på /ui/pages/listing/index.js . Lad os gå og koble det op nu.

Opkobling af en falsk listeside

Denne er hurtig. Vi bekymrer os ikke så meget om selve siden her, bare at den eksisterer for os at omdirigere brugeren til.

/ui/pages/listing/index.js

import ui from '@joystick.js/ui';

const Listing = ui.component({
  css: `
    .listing-image img {
      max-width: 100%;
      width: 100%;
      display: block;
      height: auto;
    }

    .listing-metadata {
      margin-top: 25px;
    }

    .listing-metadata .price {
      font-size: 28px;
      color: #333;
    }

    .listing-metadata .address {
      font-size: 18px;
      color: #888;
      margin-top: 7px;
    }

    .listing-metadata .rooms {
      font-size: 16px;
      color: #888;
      margin-top: 10px;
    }
  `,
  render: () => {
    return `
      <div class="container">
        <div class="listing-image">
          <img src="/house.jpg" alt="House" />
        </div>
        <div class="listing-metadata">
          <h2 class="price">$350,000</h2>
          <p class="address">1234 Fake St. Winter, MA 12345</p>
          <p class="rooms">3br, 2ba, 2,465 sqft</p>
        </div>
      </div>
    `;
  },
});

export default Listing;

Her opretter vi en Joystick-komponent ved at kalde .component() funktion defineret på ui objekt, vi importerer fra @joystick.js/ui pakke. Til den funktion sender vi et objekt af muligheder for at definere vores komponent.

Fra bunden har vi en render() funktion, som fortæller vores komponent den HTML, vi gerne vil gengive for vores komponent. Her, fordi vi ikke har brug for en fungerende side, returnerer vi bare en streng almindelig HTML med nogle hårdkodede data. Bemærk at house.jpg billede, der gengives her, kan downloades fra vores S3-bøtte her. Dette skal placeres i /public mappe i roden af ​​projektet.

Ud over dette, som vi antydede tidligere, tilføjer vi noget CSS. For at gøre det har vi på en Joystick-komponent css mulighed, som vi kan sende en streng af CSS til. Joystick omfavner automatisk denne CSS til denne komponent for at hjælpe os med at undgå at lække styles til andre komponenter.

Det er det her. Igen, dette er blot en dummy-komponent, der hjælper os med at teste den forespørgselsparameterlogik, som vi opsætter i næste afsnit.

Tilslutning af en falsk søge-UI med filtre og resultatside

Selvom der sker meget i denne komponent, er den del, vi ønsker at fokusere på, logikken til at administrere vores forespørgselsparametre. For at komme dertil, lad os først opbygge skelet-brugergrænsefladen for vores komponent og derefter pege på den faktiske logik for at få det til at fungere.

Selvom vi ikke diskuterede det tidligere, vil vi her overskrive det eksisterende indhold af /ui/pages/index/index.js fil:

/ui/pages/index/index.js

import ui from '@joystick.js/ui';

const Index = ui.component({
  css: `
    .search {
      padding: 20px;
    }

    header {
      display: flex;
      margin-bottom: 40px;
      padding-left: 20px;
    }

    header > * {
      margin-right: 20px;
    }

    .options label {
      margin-right: 10px;
    }

    .options label input {
      margin-right: 3px;
    }

    .listings ul {
      display: grid;
      grid-template-columns: 1fr;
      list-style: none;
    }

    .listings ul li {
      position: relative;
      padding: 20px;
      border: 1px solid transparent;
      cursor: pointer;
    }

    .listings ul li:hover {
      border: 1px solid #eee;
      box-shadow: 0px 1px 1px 2px rgba(0, 0, 0, 0.01);
    }

    .listings ul li a {
      position: absolute;
      inset: 0;
      z-index: 5;
    }

    .listing-image img {
      max-width: 100%;
      width: 100%;
      display: block;
      height: auto;
    }

    .listing-metadata {
      margin-top: 25px;
    }

    .listing-metadata .price {
      font-size: 24px;
      color: #333;
    }

    .listing-metadata .address {
      font-size: 16px;
      color: #888;
      margin-top: 7px;
    }

    .listing-metadata .rooms {
      font-size: 14px;
      color: #888;
      margin-top: 7px;
    }

    @media screen and (min-width: 768px) {
      .search {
        padding: 40px;
      }

      .listings ul {
        display: grid;
        grid-template-columns: 1fr 1fr;
      }  
    }

    @media screen and (min-width: 1200px) {
      .listings ul {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr 1fr;
      }  
    }
  `,
  render: () => {
    return `
      <div class="search">
        <header>
          <input type="text" name="search" placeholder="Search listings..." />
          <select name="category">
            <option value="house">House</option>
            <option value="apartment">Apartment</option>
            <option value="condo">Condo</option>
            <option value="land">Land</option>
          </select>        
          <select name="status">
            <option value="forSale">For Sale</option>
            <option value="forRent">For Rent</option>
            <option value="sold">Sold</option>
          </select>
          <div class="options">
            <label><input type="checkbox" name="hasGarage" /> Garage</label>
            <label><input type="checkbox" name="hasCentralAir" /> Central Air</label>
            <label><input type="checkbox" name="hasPool" /> Pool</label>
          </div>
          <a href="#" class="clear">Clear</a>
        </header>
        <div class="listings">
          <ul>
            <li>
              <a href="/listings/123"></a>
              <div class="listing-image">
                <img src="/house.jpg" alt="House" />
              </div>
              <div class="listing-metadata">
                <h2 class="price">$350,000</h2>
                <p class="address">1234 Fake St. Winter, MA 12345</p>
                <p class="rooms">3br, 2ba, 2,465 sqft</p>
              </div>
            </li>
          </ul>
        </div>
      </div>
    `;
  },
});

export default Index;

Ovenfor får vi kerne-HTML og CSS på siden til vores brugergrænseflade. Igen er vores mål at have en pseudo-søge-UI, hvor brugeren kan indstille nogle søgeparametre og se en liste over resultater på siden. Her bygger vi den kerne-brugergrænseflade ud og styler den op. Når vi har tilføjet dette, hvis vi besøger http://localhost:2600/ (ignorer 2605 i skærmbilledet nedenfor - dette var kun til test under skrivning) i vores browser, skulle vi se noget som dette:

Lad os derefter oprette en "standard"-tilstand for vores søge-UI (vi henviser til alt i overskriften eller den øverste del af brugergrænsefladen som "søge-UI").

/ui/pages/index/index.js

import ui from '@joystick.js/ui';

const Index = ui.component({
  state: {
    search: '',
    category: 'house',
    status: 'forSale',
    hasGarage: false,
    hasCentralAir: false,
    hasPool: false,
  },
  css: `...`,
  render: ({ state }) => {
    return `
      <div class="search">
        <header>
          <input type="text" name="search" value="${state.search}" placeholder="Search listings..." />
          <select name="category" value="${state.category}">
            <option value="house" ${state.category === 'house' ? 'selected' : ''}>House</option>
            <option value="apartment" ${state.category === 'apartment' ? 'selected' : ''}>Apartment</option>
            <option value="condo" ${state.category === 'condo' ? 'selected' : ''}>Condo</option>
            <option value="land" ${state.category === 'land' ? 'selected' : ''}>Land</option>
          </select>        
          <select name="status" value="${state.status}">
            <option value="forSale" ${state.status === 'forSale' ? 'selected' : ''}>For Sale</option>
            <option value="forRent" ${state.status === 'forRent' ? 'selected' : ''}>For Rent</option>
            <option value="sold" ${state.status === 'sold' ? 'selected' : ''}>Sold</option>
          </select>
          <div class="options">
            <label><input type="checkbox" name="hasGarage" ${state?.hasGarage ? 'checked' : ''} /> Garage</label>
            <label><input type="checkbox" name="hasCentralAir" ${state?.hasCentralAir ? 'checked' : ''} /> Central Air</label>
            <label><input type="checkbox" name="hasPool" ${state?.hasPool ? 'checked' : ''} /> Pool</label>
          </div>
          <a href="#" class="clear">Clear</a>
        </header>
        <div class="listings">
          <ul>
            <li>
              <a href="/listings/123"></a>
              <div class="listing-image">
                <img src="/house.jpg" alt="House" />
              </div>
              <div class="listing-metadata">
                <h2 class="price">$350,000</h2>
                <p class="address">1234 Fake St. Winter, MA 12345</p>
                <p class="rooms">3br, 2ba, 2,465 sqft</p>
              </div>
            </li>
          </ul>
        </div>
      </div>
    `;
  },
});

export default Index;

På en Joystick-komponent kan vi sende en state option, som er tildelt et objekt af egenskaber, som vi ønsker at tildele til vores komponents interne tilstand som standard (dvs. når komponenten først indlæses). Her opretter vi nogle standardindstillinger, som vi vil bruge til vores søge-UI.

Den vigtige del her, tilbage ned i render() funktion, er, at vi har tilføjet et argument til vores render() funktion, som vi forventer er et objekt, som vi kan destrukturere for at "plukke fra" specifikke egenskaber og tildele dem til variabler af samme navn i det aktuelle omfang/kontekst. Objektet, vi forventer her, er component instans (hvilket betyder den komponent, vi i øjeblikket er ved at oprette, som den findes i hukommelsen).

I det tilfælde forventer vi at have adgang til den nuværende state værdi. "State" i dette tilfælde refererer til den visuelle tilstand af vores brugergrænseflade. Værdierne på state objekt er beregnet til at være et middel til at forstærke denne visuelle tilstand i farten.

Her tager vi den state objekt for at referere til værdierne for at udfylde vores søge-UI. Vi har tre typer input i vores brugergrænseflade:

  1. input som er en almindelig tekstinput, der bruges til at indtaste en streng søgetekst.
  2. select som bruges til vores liste "kategori" og "status" input.
  3. checkbox som bruges til vores faciliteter afkrydsningsfelter.

Nede i vores HTML refererer vi til disse værdier ved hjælp af JavaScript-strenginterpolation (en funktion på sprogniveau til indlejring/evaluering af JavaScript inde i en streng). Vi kan gøre dette, fordi værdien vi returnerer fra vores komponents render() funktion er en streng.

Afhængigt af den type input, vi gengiver, bruger vi den tilsvarende tilstandsværdi lidt anderledes. Til vores søgning i almindelig tekst kan vi bare indstille en value attribut svarende til værdien af ​​state.search .

For vores vælg <select> input sætter vi både en value attribut på hoved-<select> tag samt en betinget selected attribut på hver mulighed i den <select> liste (vigtigt, som om vi ikke gør dette, den aktuelle værdi af inputtet vises ikke som valgt uden denne attribut).

Til sidst, til vores afkrydsningsfeltinput, tilføjer vi betinget en checked attributværdi baseret på den tilsvarende state værdi for hvert input.

Dette giver os det grundlæggende i vores brugergrænseflade. Nu er vi klar til at oprette forbindelse til registrering af ændringer til vores søge-UI og gemme dem som forespørgselsparametre i vores URL.

Indfangning af søgefiltre som forespørgselsparametre

Nu hvor vi har vores basis-UI-sæt, kan vi begynde at administrere vores forespørgselsparametre. For at gøre det vil vi tilføje nogle JavaScript-hændelseslyttere til vores brugergrænseflade, så vi kan få fat i de seneste værdier, som de er indstillet af brugeren:

/ui/pages/index/index.js

import ui from '@joystick.js/ui';
import queryString from 'query-string';

const Index = ui.component({
  state: { ... },
  methods: {
    handleUpdateQueryParams: (param = '', value = '') => {
      const existingQueryParams = queryString.parse(location.search);
      const updatedQueryParams = queryString.stringify({
        ...existingQueryParams,
        [param]: value,
      });

      window.history.pushState('', '', `?${updatedQueryParams}`);
    },
    handleClearQueryParams: (component = {}) => {
      window.history.pushState('', '', `${location.origin}${location.pathname}`);
      component.methods.handleSetStateFromQueryParams();
    },
  },
  css: `...`,
  events: {
    'keyup [name="search"]': (event, component = {}) => {
      component.methods.handleUpdateQueryParams('search', event.target.value);
    },
    'change [name="category"]': (event, component = {}) => {
      component.methods.handleUpdateQueryParams('category', event.target.value);
    },
    'change [name="status"]': (event, component = {}) => {
      component.methods.handleUpdateQueryParams('status', event.target.value);
    },
    'change [type="checkbox"]': (event, component = {}) => {
      component.methods.handleUpdateQueryParams(event.target.name, event.target.checked);
    },
    'click .clear': (event, component = {}) => {
      event.preventDefault();
      component.methods.handleClearQueryParams();
    },
  },
  render: ({ state }) => {
    return `
      <div class="search">
        ...
      </div>
    `;
  },
});

export default Index;

Ovenfor har vi tilføjet to nye egenskaber til vores komponents muligheder:events og methods . Fokus på events , her hjælper Joystick os med at lytte efter JavaScript DOM-hændelser på elementer, der gengives af vores komponent. Hver hændelse er defineret som en egenskab på objektet, der sendes til events hvor ejendomsnavnet er en streng, der beskriver typen af ​​DOM-begivenhed, der skal lyttes efter, og elementet inde i vores komponent, der skal lytte efter hændelsen .

Til egenskaben tildeler vi en funktion, der skal kaldes, når den hændelse detekteres på det angivne element. Her har vi tilføjet lyttere til hver af vores søgerelaterede input (bortset fra afkrydsningsfeltet input, som vi bare lytter efter generisk på input med en type checkbox ).

Bemærk, at den ulige and herude er search tekstinput. Her vil vi lytte efter keyup hændelse på input, da vi ønsker at fange hver ændring af input (hvis vi lytter efter en change begivenhed ligesom vi gør med de andre, vil den kun udløses, når brugeren har "sløret" eller klikket ud af inputtet).

Indenfor alle begivenhedslyttere (med undtagelse af det sidste, som vi vil dække om lidt), ringer vi til component.methods.handleUpdateQueryParams() . Til en begivenhedslytters tilbagekaldsfunktion sender Joystick to værdier:event og component . event er den rå JavaScript DOM-hændelse, der udløste og component er den aktuelle komponentinstans (svarende til det, vi så nede i render() ) – = {} del efter component her definerer vi en standardværdi – en kerne JavaScript-funktion – at falde tilbage til i tilfælde af, at component er ikke defineret (dette vil aldrig være sandt, da det er automatisk – overvej at tilføje dette som en vanekraft).

Fra component for eksempel vil vi have adgang til en metode, der er defineret på methods objekt (hvor vi kan gemme diverse metoder på vores komponentinstans). Her kalder vi til en metode defineret ovenfor, handleUpdateQueryParams() .

Ovenpå har vi tilføjet en import af queryString pakke, vi installerede tidligere, som vil hjælpe os med at parse de eksisterende forespørgselsparametre i URL'en og forberede vores værdier til addition til URL'en.

Indersiden af ​​handleUpdateQueryParams() , vi er nødt til at forudse eksisterende forespørgselsparametre i vores URL, som vi tilføjer til, så vi begynder med at gribe alle eksisterende forespørgselsparametre og parse dem til et objekt med queryString.parse() . Her location.search er den globale browserværdi, der indeholder den aktuelle forespørgselsstreng som f.eks. ?someParam=value . Når vi sender denne værdi til queryString.parse() vi får et JavaScript-objekt tilbage som { someParam: 'value' } .

Med det opretter vi en anden variabel updatedQueryParams som er indstillet til et opkald til queryString.stringify() og sendte et objekt, som vi ønsker at konvertere tilbage til en forespørgselsstreng som ?someParam=value .

På det objekt ved hjælp af JavaScript ... spread-operatør, "pakker" vi først ud eller spreder eventuelle eksisterende forespørgselsparametre og følger dem derefter straks med [param]: value hvor param er navnet på den param, vi ønsker at opdatere (overført som det første argument til handleUpdateQueryParams() ) og value er den værdi, vi ønsker at indstille for den parameter – indstillet via det andet argument, der er sendt til handleUpdateQueryParams() . [param] syntaks her bruger JavaScript-parentesnotation til at sige "indstil egenskabsnavnet dynamisk til værdien af ​​param argument."

Hvis vi kigger ned i vores hændelseshandlere for at se, hvordan dette kaldes, sender vi param enten som en streng eller i tilfælde af vores afkrydsningsfeltinput, som event.target.name værdi eller name attribut for afkrydsningsfeltet, der udløser hændelsen.

Med updatedQueryParams kompileret, for at opdatere vores URL, kalder vi til den globale window.history.pushState() sender en opdatering, vi ønsker at anvende på URL'en. Her history.pushState() er en funktion, der opdaterer vores browsers historik men udløser ikke en browseropdatering (som vi ville forvente, hvis vi manuelt indstiller location.search værdi direkte).

Ganske vist API for history.pushState() er lidt forvirrende (som nævnt i denne MDN-artikel om funktionen her). For de to første værdier sender vi blot tomme strenge (se det forrige link på MDN, hvis du er nysgerrig efter, hvad disse er til), og for det tredje argument sender vi den URL, vi vil "skubbe" ind i browserhistorikken.

I dette tilfælde ønsker vi ikke at ændre selve URL-adressen, kun forespørgselsparametrene, så vi sender en streng, der indeholder en ? som angiver begyndelsen af ​​forespørgselsparametre i en URL og værdien returneret af queryString.stringify() i updatedQueryParams .

Det er det. Hvis vi nu begynder at foretage ændringer i vores brugergrænseflade, bør vi se, at vores webadresse begynder at opdatere dynamisk med inputværdierne for vores søgebrugergrænseflade.

Inden vi går videre, gør du hurtigt opmærksom på click .clear hændelseslytter og efterfølgende opkald til methods.handleClearQueryParams() , her gør vi, hvad koden foreslår:at rydde alle forespørgselsparametre, vi har angivet på URL'en, når brugeren klikker på linket "Ryd" i slutningen af ​​vores søge-UI.

For at gøre det ringer vi til sidst til history.pushState() , denne gang passerer kombinationen af ​​den nuværende location.origin (f.eks. http://localhost:2600 ) med den nuværende location.pathname (f.eks. / eller /listings/123 ). Dette fjerner effektivt alle forespørgselsparametre i URL'en og fjerner den til kun basis-URL'en for den aktuelle side.

Herefter kalder vi til en anden metode, vi endnu ikke har defineret:methods.handleSetStateFromQueryParams() . Vi vil se, hvordan dette tager form i næste – og sidste – afsnit.

Genindlæser søgefiltre, når siden indlæses

Denne del er ret ligetil. Nu hvor vi har vores forespørgselsparametre i vores URL, vil vi tage højde for disse parametre, når vores side indlæses. Husk, vi ønsker at kunne flytte væk fra denne side, komme tilbage og få vores søge-UI til at "genindlæse" brugerens søgeværdier fra URL'en.

/ui/pages/index/index.js

import ui from '@joystick.js/ui';
import queryString from 'query-string';

const Index = ui.component({
  state: { ... },
  lifecycle: {
    onMount: (component = {}) => {
      component.methods.handleSetStateFromQueryParams();
    },
  },
  methods: {
    handleSetStateFromQueryParams: (component = {}) => {
      const queryParams = queryString.parse(location.search);
      component.setState({
        search: queryParams?.search || '',
        category: queryParams?.category || 'house',
        status: queryParams?.status || 'forSale',
        hasGarage: queryParams?.hasGarage && queryParams?.hasGarage === 'true' || false,
        hasCentralAir: queryParams?.hasCentralAir && queryParams?.hasCentralAir === 'true' || false,
        hasPool: queryParams?.hasPool && queryParams?.hasPool === 'true' || false,
      });
    },
    handleUpdateQueryParams: (param = '', value = '') => { ... },
    handleClearQueryParams: (component = {}) => {
      window.history.pushState('', '', `${location.origin}${location.pathname}`);
      component.methods.handleSetStateFromQueryParams();
    },
  },
  css: `...`,
  events: { ... },
  render: ({ state }) => {
    return `
      <div class="search">
        ...
      </div>
    `;
  },
});

export default Index;

Sidste del. Ovenfor har vi tilføjet en ekstra egenskab til vores komponentindstillinger lifecycle og på det objekt, der er sendt til det, har vi defineret en funktion onMount ved at bruge component instans som det første argument.

Her siger vi "når disse komponenter monteres (indlæses) i browseren, ring til methods.handleSetStateFromQueryParams() fungere. Ideen er, hvad du ville forvente:at indlæse det aktuelle sæt af forespørgselsparametre fra URL'en tilbage til vores komponents tilstand, når siden indlæses.

Fokus på handleSetStateFromQueryParams() , arbejdet her er ret simpelt. Først ønsker vi at få forespørgselsparametrene som et objekt queryParams ved at ringe til queryString.parse(location.search) . Dette ligner det, vi så tidligere, med ?someParam=value form af vores forespørgselsparametre og konvertere det til et JavaScript-objekt som { someParam: 'value' } .

Med det objekt queryParams , ringer vi til component.setState() til dynamisk at opdatere tilstanden af ​​vores komponent. Her indstiller vi hver af de værdier, vi har angivet i vores komponents standard state tidligere. For hver værdi forsøger vi at få adgang til denne parameter fra queryParams objekt. Hvis det findes, bruger vi det, og hvis ikke, bruger vi JavaScript eller || operatør for at sige "brug denne værdi i stedet for." Her falder "i stedet" bare tilbage til de samme værdier, som vi satte på standardtilstanden tidligere.

Det er det! Når vi nu indstiller nogle søgeværdier og opdaterer siden, forbliver vores forespørgselsparametre og bliver automatisk sat tilbage på vores brugergrænseflade, hvis vi opdaterer siden. Hvis vi klikker på den falske fortegnelse på vores liste for at gå til dens detaljeside og derefter klikker på "tilbage" i browseren, vil vores forespørgselsparametre stadig eksistere i URL'en og blive indlæst tilbage i brugergrænsefladen.

Afslutning

I denne øvelse lærte vi, hvordan man dynamisk indstiller forespørgselsparametre i browseren. Vi lærte, hvordan man opretter en enkel, dynamisk søge-UI, der lagrede brugerens søgeparametre i URL'en, og når siden genindlæses, hvordan man indlæser disse parametre fra URL'en tilbage til vores UI. For at gøre det lærte vi, hvordan man bruger de forskellige funktioner i en Joystick-komponent i forbindelse med query-string pakke for at hjælpe os med at kode og afkode forespørgselsparametrene i vores URL.