Cara menggunakan API pencarian Wikipedia untuk membangun antarmuka pengguna dengan RamdaJS

Dalam tutorial ini, kita akan membangun UI menggunakan API pencarian publik Wikipedia bersama dengan beberapa JavaScript + RamdaJS.

Mulai

Berikut tautan GitHub dan tautan Codesandbox. Buka terminal Anda dan pilih direktori untuk mengkloningnya.

git clone [//github.com/yazeedb/ramda-wikipedia-search](//github.com/yazeedb/ramda-wikipedia-search) cd ramda-wikipedia-search yarn install (or npm install) 

The mastercabang memiliki proyek selesai, jadi memeriksa startcabang jika Anda ingin kode bersama.

git checkout start

Dan mulai proyeknya!

npm start

Browser Anda akan secara otomatis membuka localhost: 1234.

Mendapatkan Nilai Input

Inilah aplikasi awalnya.

Untuk menangkap masukan pengguna saat mereka mengetik, inputelemen kita membutuhkan pendengar peristiwa.

src/index.jsFile Anda sudah terhubung dan siap digunakan. Anda akan melihat kami mengimpor Bootstrap untuk penataan.

Mari tambahkan pendengar acara dummy untuk menyelesaikan semuanya.

import 'bootstrap/dist/css/bootstrap.min.css'; const inputElement = document.querySelector('input'); inputElement.addEventListener('keyup', (event) => { console.log('value:', event.target.value); }); 

Kami tahu event.target.valuecara standar untuk mengakses nilai masukan. Sekarang ini menunjukkan nilainya.

Bagaimana Ramda dapat membantu kami mencapai hal-hal berikut?

  • Mengambil event.target.value
  • Pangkas keluaran (strip di depan / di belakang spasi)
  • Default untuk string kosong jika undefined

The pathOrFungsi benar-benar dapat menangani poin-poin pertama dan ketiga. Dibutuhkan tiga parameter: default, jalur, dan data.

Jadi berikut ini bekerja dengan sempurna

import { pathOr } from 'ramda'; const getInputValue = pathOr('', ['target', 'value']); 

Jika event.target.valueadalah undefined, kita akan mendapatkan kembali string kosong!

Ramda juga memiliki trimfungsi untuk mengatasi masalah whitespace kita.

import { pathOr, trim } from 'ramda'; const getInputValue = (event) => trim(pathOr('', ['target', 'value'], event)); 

Alih-alih menumpuk fungsi tersebut, mari gunakan pipe. Lihat artikel saya tentang pipa jika itu baru bagi Anda.

import { pathOr, pipe, trim } from 'ramda'; const getInputValue = pipe( pathOr('', ['target', 'value']), trim ); 

Kami sekarang memiliki fungsi tersusun yang mengambil eventobjek, mengambilnya target.value, defaultnya '', dan memangkasnya.

Cantik.

Saya sarankan untuk menyimpan ini dalam file terpisah. Mungkin menyebutnya getInputValue.jsdan menggunakan sintaks ekspor default.

Mendapatkan URL Wikipedia

Saat tulisan ini dibuat, URL pencarian API Wikipedia adalah //en.wikipedia.org/w/api.php?origin=*&action=opensearch&search=

Untuk penelusuran yang sebenarnya, cukup tambahkan topik. Jika Anda membutuhkan beruang, misalnya, URL terlihat seperti ini:

//en.wikipedia.org/w/api.php?origin=*&action=opensearch&search=bears

Kami menginginkan fungsi yang mengambil topik dan mengembalikan URL pencarian Wikipedia secara lengkap. Saat pengguna mengetik, kami membuat URL berdasarkan masukan mereka.

Ramda concatbekerja dengan baik di sini.

import { concat } from 'ramda'; const getWikipediaSearchUrlFor = concat( '//en.wikipedia.org/w/api.php?origin=*&action=opensearch&search=' ); 

concat, sesuai dengan namanya, menggabungkan string dan array. Itu curried sehingga memberikan URL sebagai satu argumen mengembalikan fungsi yang mengharapkan string kedua. Lihat artikel saya tentang kari jika masih baru!

Masukkan kode itu ke dalam modul yang disebut getUrl.js.

Sekarang mari perbarui index.js. Impor dua modul baru kami, bersama dengan pipedan tapdari Ramda.

import 'bootstrap/dist/css/bootstrap.min.css'; import { pipe, tap } from 'ramda'; import getInputValue from './getInputValue'; import getUrl from './getUrl'; const makeUrlFromInput = pipe( getInputValue, getUrl, tap(console.warn) ); const inputElement = document.querySelector('input'); inputElement.addEventListener('keyup', makeUrlFromInput); 

Kode baru ini membangun URL permintaan kami dari input pengguna dan masuk melalui tap.

Saksikan berikut ini.

Membuat Permintaan AJAX

Langkah selanjutnya adalah memetakan URL tersebut ke permintaan AJAX dan mengumpulkan respons JSON.

Ganti makeUrlFromInputdengan fungsi baru searchAndRenderResults,.

const searchAndRenderResults = pipe( getInputValue, getUrl, (url) => fetch(url) .then((res) => res.json()) .then(console.warn) ); 

Jangan lupa untuk mengubah pendengar acara Anda juga!

inputElement.addEventListener('keyup', searchAndRenderResults); 

Inilah hasil kami.

Membuat Komponen Hasil

Sekarang setelah kita memiliki JSON, mari buat komponen yang membuatnya.

Tambahkan Results.jske direktori Anda.

Lihat kembali tanggapan JSON penelusuran Wikipedia kami. Perhatikan bentuknya. Ini adalah array dengan indeks berikut:

  1. Kueri (apa yang Anda telusuri)
  2. Array nama hasil
  3. Susunan ringkasan
  4. Array of links to results

Our component can take an array of this shape and return a nicely formatted list. Through ES6 array destructuring, we can use that as our function signature.

Edit Results.js

export default ([query, names, summaries, links]) => ` 

Searching for "${query}"

    ${names.map( (name, index) => `
  • ${name}

    ${summaries[index]}

  • ` )}
`;

Let’s go step by step.

Original text


  • It’s a function that takes an array of our expected elements: query, names, summaries, and links.
  • Using ES6 template literals, it returns an HTML string with a title and a list.
  • Inside the
      we map names to
    • tags, so one for each.
    • Inside those are tags pointing to each result’s link. Each link opens in a new tab.
    • Below the link is a paragraph summary.

    Import this in index.js and use it like so:

    // ... import Results from './Results'; // ... const searchAndRenderResults = pipe( getInputValue, getUrl, (url) => fetch(url) .then((res) => res.json()) .then(Results) .then(console.warn) ); 

    This passes the Wikipedia JSON to Results and logs the result. You should be seeing a bunch of HTML in your DevTools console!

    All that’s left is to render it to the DOM. A simple render function should do the trick.

    const render = (markup) => { const resultsElement = document.getElementById('results'); resultsElement.innerHTML = markup; }; 

    Replace console.warn with the render function.

    const searchAndRenderResults = pipe( getInputValue, getUrl, (url) => fetch(url) .then((res) => res.json()) .then(Results) .then(render) ); 

    And check it out!

    Each link should open in a new tab.

    Removing Those Weird Commas

    You may have noticed something off about our fresh UI.

    It has extra commas! Why??

    Template Literals

    It’s all about how template literals join things. If you stick in an array, it’ll join it using the toString() method.

    See how this becomes joined?

    const joined = [1, 2, 3].toString(); console.log(joined); // 1,2,3 console.log(typeof joined); // string 

    Template literals do that if you put arrays inside of them.

    const nums = [1, 2, 3]; const msg = `My favorite nums are ${nums}`; console.log(msg); // My favorite nums are 1,2,3 

    You can fix that by joining the array without commas. Just use an empty string.

    const nums = [1, 2, 3]; const msg = `My favorite nums are ${nums.join('')}`; console.log(msg); // My favorite nums are 123 

    Edit Results.js to use the join method.

    export default ([query, names, summaries, links]) => ` 

    Searching for "${query}"

      ${names .map( (name, index) => `
    • ${name}

      ${summaries[index]}

    • ` ) .join('')}
    `;

    Now your UI’s much cleaner.

    Fixing a Little Bug

    I found a little bug while building this. Did you notice it?

    Emptying the input throws this error.

    That’s because we’re sending an AJAX request without a search topic. Check out the URL in your Network tab.

    That link points to a default HTML page. We didn’t get JSON back because we didn’t specify a search topic.

    To prevent this from happening we can avoid sending the request if the input's empty.

    We need a function that does nothing if the input's empty, and does the search if it’s filled.

    Let’s first create a function called doNothing. You can guess what it looks like.

    const doNothing = () => {}; 

    This is better known as noOp, but I like doNothing in this context.

    Next remove getInputValue from your searchAndRenderResults function. We need a bit more security before using it.

    const searchAndRenderResults = pipe( getUrl, (url) => fetch(url) .then((res) => res.json()) .then(Results) .then(render) ); 

    Import ifElse and isEmpty from Ramda.

    import { ifElse, isEmpty, pipe, tap } from 'ramda'; 

    Add another function, makeSearchRequestIfValid.

    const makeSearchRequestIfValid = pipe( getInputValue, ifElse(isEmpty, doNothing, searchAndRenderResults) ); 

    Take a minute to absorb that.

    If the input value’s empty, do nothing. Else, search and render the results.

    You can gather that information just by reading the function. That’s expressive.

    Ramda’s isEmpty function works with strings, arrays, objects.

    This makes it perfect to test our input value.

    ifElse fits here because when isEmpty returns true, doNothing runs. Otherwise searchAndRenderResults runs.

    Lastly, update your event handler.

    inputElement.addEventListener('keyup', makeSearchRequestIfValid); 

    And check the results. No more errors when clearing the input!

    This tutorial was from mycompletely freecourse on Educative.io, Functional Programming Patterns With RamdaJS!

    Please consider taking/sharing it if you enjoyed this content.

    It’s full of lessons, graphics, exercises, and runnable code samples to teach you a basic functional programming style using RamdaJS.

    Thank you for reading ❤️