Reputation: 395
The following code
const endpoint = 'https://raw.githubusercontent.com/Hipo/university-domains-list/master/world_universities_and_domains.json';
const universities = [];
fetch(endpoint)
.then(results => results.json())
.then(data => universities.push(...data));
console.log(universities);
function findMatches(wordToMatch, universities) {
return universities.filter(uni => {
const regex = new RegExp(wordToMatch, 'gi');
return uni.name.match(regex)
})
}
export default findMatches;
returns the error below
'Uncaught TypeError: Cannot read property 'filter' of undefined'
I can log the data using console.log(universities). So why can't I filter through it? FYI the data is an array of objects. Any help is massivaly appreciated. Thank you.
Upvotes: 1
Views: 11437
Reputation: 395
I just want to let everybody know I finally got things working. I had to install babel-polyfill and babel-preset-env and add to webpack to get UglifyJS to work with async await and to optimise bundle size.
I had to use async await instead of regular promises to get the HTML to render into the DOM for some reason, not sure why. Anyway here is the code that finally worked as expected:
UniFetch.js
const endpoint = 'https://raw.githubusercontent.com/Hipo/university-domains-list/master/world_universities_and_domains.json';
const universities = [];
const promise = fetch(endpoint)
.then(blob => blob.json())
.then(data => universities.push(...data.slice(8286, 8456)));
function findMatches(wordToMatch) {
return promise.then(() => universities.filter(uni => {
const regex = new RegExp(wordToMatch, 'gi');
return uni.name.match(regex)
}));
}
async function displayMatches() {
searchResults.innerHTML = await findMatches(this.value)
.then(arr => arr.map(uni => {
return `
<li>${uni.name}</li>
`
}));
}
const searchInput = document.querySelector("input[name='unisearch']");
const searchResults = document.querySelector('.unisearch__results');
searchInput.addEventListener('change', displayMatches);
searchInput.addEventListener('keyup', displayMatches);
export default findMatches
App.js
import FindMatches from '../UniFetch.js'
FindMatches()
Hope this helps some people to implement a typeahead, autocomplete API fetch.
Upvotes: 1
Reputation: 5456
You need to remove universities
as a parameter in your findMatches
function because it is overriding the value of the local universities
variable:
function findMatches(wordToMatch) {
return universities.filter(uni => {
const regex = new RegExp(wordToMatch, 'gi');
return uni.name.match(regex)
})
}
You can then proceed to use the findMatches
function as follows:
findMatches("hi") // returns a filtered array
Edit:
You have a race condition in your code, wherein findMatches
might be called
before your fetch
is complete. To fix the issue, findMatches
should return a promise like so:
const endpoint = 'https://raw.githubusercontent.com/Hipo/university-domains-list/master/world_universities_and_domains.json';
const universities = [];
const promise = fetch(endpoint)
.then(results => results.json())
.then(data => universities.push(...data));
console.log(universities);
function findMatches(wordToMatch) {
return promise.then(() => universities.filter(uni => {
const regex = new RegExp(wordToMatch, 'gi');
return uni.name.match(regex)
}));
}
findMatches("hi").then(arr => console.log(arr));
If you're absolutely sure that findMatches
will always be called after fetch
is complete, you can go with the first solution. Otherwise, it is strongly recommended you go with the second solution that uses promises.
Upvotes: 3