Fixing a Little Bug

The app sends AJAX requests even if the input's empty. We can fix that! (5 min. read)

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

widget

Emptying the input throws this error.

widget

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

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

widget

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.

Press + to interact
import 'bootstrap/dist/css/bootstrap.min.css';
import { pipe, tap } from 'ramda';
import getInputValue from './getInputValue';
import getUrl from './getUrl';
import Results from './Results';
const doNothing = () => {};
const render = markup => {
const resultsElement = document.getElementById('results');
resultsElement.innerHTML = markup;
};
const searchAndRenderResults = pipe(
getInputValue,
getUrl,
url =>
fetch(url)
.then(res => res.json())
.then(Results)
.then(render)
);
const inputElement = document.querySelector('input');
inputElement.addEventListener('keyup', searchAndRenderResults);

Just trust me for now :D

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

Press + to interact
import 'bootstrap/dist/css/bootstrap.min.css';
import { pipe, tap } from 'ramda';
import getInputValue from './getInputValue';
import getUrl from './getUrl';
import Results from './Results';
const doNothing = () => {};
const render = markup => {
const resultsElement = document.getElementById('results');
resultsElement.innerHTML = markup;
};
const searchAndRenderResults = pipe(
getUrl,
url =>
fetch(url)
.then(res => res.json())
.then(Results)
.then(render)
);
const inputElement = document.querySelector('input');
inputElement.addEventListener('keyup', searchAndRenderResults);

And create a new function, makeSearchRequestIfValid. This will use getInputValue.

Press + to interact
import 'bootstrap/dist/css/bootstrap.min.css';
import { ifElse, isEmpty, pipe, tap } from 'ramda';
import getInputValue from './getInputValue';
import getUrl from './getUrl';
import Results from './Results';
const doNothing = () => {};
const render = markup => {
const resultsElement = document.getElementById('results');
resultsElement.innerHTML = markup;
};
const searchAndRenderResults = pipe(
getUrl,
url =>
fetch(url)
.then(res => res.json())
.then(Results)
.then(render)
);
const makeSearchRequestIfValid = pipe(
getInputValue,
ifElse(isEmpty, doNothing, searchAndRenderResults)
);
const inputElement = document.querySelector('input');
inputElement.addEventListener('keyup', searchAndRenderResults);

Take a minute to absorb this snippet.

Press + to interact
const makeSearchRequestIfValid = pipe(
getInputValue,
ifElse(isEmpty, doNothing, searchAndRenderResults)
);

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. Here’s a screenshot from their site.

widget

This makes it perfect to test our input value.

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

Update your event handler

Press + to interact
inputElement.addEventListener('keyup', makeSearchRequestIfValid);

And check the results. No more errors!

widget