Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Last active August 17, 2019 20:08
Show Gist options
  • Select an option

  • Save ryanflorence/3042134bfe5c3121c8fc93db7a62bcbc to your computer and use it in GitHub Desktop.

Select an option

Save ryanflorence/3042134bfe5c3121c8fc93db7a62bcbc to your computer and use it in GitHub Desktop.

Revisions

  1. ryanflorence revised this gist Apr 29, 2019. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion App.iTunes.jsx
    Original file line number Diff line number Diff line change
    @@ -52,7 +52,6 @@ export default function ITunes() {
    }`}
    style={styles.option}
    >
    {console.log(song)}
    <div style={styles.imageWrapper}>
    <img
    alt={song.collectionName}
  2. ryanflorence revised this gist Apr 29, 2019. 1 changed file with 4 additions and 7 deletions.
    11 changes: 4 additions & 7 deletions App.CitySearch.jsx
    Original file line number Diff line number Diff line change
    @@ -15,15 +15,12 @@ function ServerCitySearch() {

    return (
    <div style={{ maxWidth: 600, margin: "auto" }}>
    <h2 id="description">Server City Search</h2>
    <Combobox>
    <ComboboxInput
    onChange={handleSearchTermChange}
    aria-labelledby="description"
    />
    <h2>Server City Search</h2>
    <Combobox ariaLabel="City Search">
    <ComboboxInput onChange={handleSearchTermChange} />
    <ComboboxPopup>
    <RandomFocasableJunk cities={cities} />
    <ComboboxList aria-labelledby="description">
    <ComboboxList>
    {cities.map(city => {
    let str = `${city.city}, ${city.state}`;
    return <ComboboxOption key={str} value={str} />;
  3. ryanflorence revised this gist Apr 29, 2019. 3 changed files with 135 additions and 0 deletions.
    85 changes: 85 additions & 0 deletions App.CitySearch.jsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    import React, { useState, useEffect } from "react";
    import "./packages/combobox/styles.css";
    import {
    Combobox,
    ComboboxInput,
    ComboboxList,
    ComboboxOption,
    ComboboxPopup
    } from "./packages/combobox/index";

    function ServerCitySearch() {
    const [searchTerm, setSearchTerm] = useState("");
    const cities = useCitySearch(searchTerm);
    const handleSearchTermChange = event => setSearchTerm(event.target.value);

    return (
    <div style={{ maxWidth: 600, margin: "auto" }}>
    <h2 id="description">Server City Search</h2>
    <Combobox>
    <ComboboxInput
    onChange={handleSearchTermChange}
    aria-labelledby="description"
    />
    <ComboboxPopup>
    <RandomFocasableJunk cities={cities} />
    <ComboboxList aria-labelledby="description">
    {cities.map(city => {
    let str = `${city.city}, ${city.state}`;
    return <ComboboxOption key={str} value={str} />;
    })}
    </ComboboxList>
    </ComboboxPopup>
    </Combobox>
    </div>
    );
    }

    function useCitySearch(searchTerm) {
    const [cities, setCities] = useState([]);

    useEffect(
    () => {
    if (searchTerm.trim() !== "") {
    let current = true;
    fetchCities(searchTerm).then(cities => {
    if (current) {
    setCities(cities);
    }
    });
    return () => (current = false);
    }
    },
    [searchTerm]
    );

    return cities;
    }

    function RandomFocasableJunk({ cities }) {
    return (
    <p
    style={{
    textAlign: "center",
    padding: "5px",
    margin: "0",
    color: "#888",
    fontStyle: "italic"
    }}
    >
    {cities.length} results <a href="https://google.com">Google</a>{" "}
    <button>Dangit</button>
    </p>
    );
    }

    async function fetchCities(value) {
    try {
    let res = await fetch(`http://localhost:5000/?${value}`);
    return await res.json();
    } catch (e) {
    throw e;
    }
    }

    export default ServerCitySearch;
    50 changes: 50 additions & 0 deletions App.Clientside.jsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,50 @@
    import React, { useState, useMemo } from "react";
    import "./packages/combobox/styles.css";
    import {
    Combobox,
    ComboboxInput,
    ComboboxList,
    ComboboxOption,
    ComboboxPopup
    } from "./packages/combobox/index";
    import cities from "./cities";
    import matchSorter from "match-sorter";
    import { useThrottle } from "use-throttle";

    export default function ClientSearch() {
    let [term, setTerm] = useState("");
    let throttledTerm = useThrottle(term, 100);

    let results = useMemo(
    () =>
    term.trim() === ""
    ? null
    : matchSorter(cities, term, {
    keys: [item => `${item.city}, ${item.state}`]
    }),
    [throttledTerm]
    );

    const handleChange = event => setTerm(event.target.value);

    return (
    <div style={{ maxWidth: 600, margin: "auto" }}>
    <h2 id="demo">Clientside Search</h2>
    <Combobox ariaLabel="Cities">
    <ComboboxInput onChange={handleChange} autocompleteOnNav={false} />
    <ComboboxPopup>
    {results && (
    <ComboboxList>
    {results.slice(0, 10).map((result, index) => (
    <ComboboxOption
    key={index}
    value={`${result.city}, ${result.state}`}
    />
    ))}
    </ComboboxList>
    )}
    </ComboboxPopup>
    </Combobox>
    </div>
    );
    }
    File renamed without changes.
  4. ryanflorence created this gist Apr 29, 2019.
    116 changes: 116 additions & 0 deletions App.iTunes.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,116 @@
    import React, { useState, useEffect } from "react";
    import "./packages/combobox/styles.css";
    import {
    Combobox,
    ComboboxInput,
    ComboboxList,
    ComboboxOption,
    ComboboxOptionText,
    ComboboxPopup
    } from "./packages/combobox/index";
    import { useThrottle } from "use-throttle";
    import uniqBy from "lodash.uniqby";

    const styles = {
    option: {
    display: "flex",
    alignItems: "center",
    paddingRight: 10
    },
    imageWrapper: {
    background: "#eee",
    width: 30,
    height: 30,
    textAlign: "center"
    },
    optionTextWrapper: {
    marginLeft: 10,
    whiteSpace: "nowrap",
    textOverflow: "ellipsis",
    overflow: "hidden"
    }
    };

    export default function ITunes() {
    const [searchTerm, setSearchTerm] = useState(null);
    const songs = useSongSearch(searchTerm);
    const handleSearchTermChange = event => setSearchTerm(event.target.value);

    return (
    <div style={{ maxWidth: 600, margin: "auto" }}>
    <h2>iTunes Search</h2>
    <Combobox ariaLabel="iTunes Search">
    <ComboboxInput onChange={handleSearchTermChange} />
    <ComboboxPopup>
    <ComboboxList>
    {songs &&
    songs.map(song => (
    <ComboboxOption
    key={song.trackId}
    value={`${song.trackName}: ${song.collectionName}, ${
    song.artistName
    }`}
    style={styles.option}
    >
    {console.log(song)}
    <div style={styles.imageWrapper}>
    <img
    alt={song.collectionName}
    src={song.artworkUrl60}
    height="30"
    width="30"
    />
    </div>
    <div style={styles.optionTextWrapper}>
    <ComboboxOptionText />
    </div>
    </ComboboxOption>
    ))}
    </ComboboxList>
    </ComboboxPopup>
    </Combobox>
    </div>
    );
    }

    async function fetchSongs(value) {
    try {
    let res = await fetch(`https://itunes.now.sh/?term=${value}`);
    let json = await res.json();
    let songs = json.results.filter(song => song.trackName);
    let unique = uniqBy(
    songs,
    song => `${song.trackName}, ${song.collectionName}`
    );
    return unique.slice(0, 10);
    } catch (e) {
    return Promise.resolve(null);
    }
    }

    function useSongSearch(searchTerm) {
    const [results, setResults] = useState([]);
    const throttled = useThrottle(searchTerm, 500);

    useEffect(
    () => {
    if (throttled) {
    if (throttled.trim() !== "") {
    let current = true;
    console.log("fetching", throttled);
    fetchSongs(throttled).then(results => {
    console.log("fetch finished", throttled);
    if (current) {
    console.log("setting results", throttled);
    setResults(results);
    }
    });
    return () => (current = false);
    }
    }
    },
    [throttled]
    );

    return results;
    }