0

I am trying to turn a for loop into a forEach loop, but it doesn't seem to be working...

Here is my code:

const townDataURL = "[some link I probably can't disclose...]"
const towns2get = [
    "Preston",
    "Fish Haven",
    "Soda Springs"
]

fetch(townDataURL)
    .then((response) => {
        return response.json()
    })
    .then((jsonData) => {
        const towns = jsonData["towns"].filter((item) => {
            // for (let i = 0; i<towns2get.length; i++) {
            //     if (item.name == towns2get[i]) {
            //         return item
            //     }
            // }
            return (towns2get.forEach(elem => {
                return ( (item.name == elem) ? (item) : "Hello?" )
            }))
        })
        console.log(towns)
    })

When I have the commented code run it gives me this:

(3) [{…}, {…}, {…}]
0: {name: "Fish Haven", photo: "fishhaven.jpg", motto: "This is Fish Heaven.", yearFounded: 1864, currentPopulation: 501, …}
1: {name: "Preston", photo: "preston.jpg", motto: "Home of Napoleon Dynamite.", yearFounded: 1866, currentPopulation: 5204, …}
2: {name: "Soda Springs", photo: "sodasprings.jpg", motto: "Historic Oregon Trail Oasis. The Soda is on Us.", yearFounded: 1858, currentPopulation: 2985, …}
length: 3
__proto__: Array(0)

Which is exactly what I want, but I want to simplify my code... what I have now gives me this:


[]
length: 0
__proto__: Array(0)

I've done some debugging and I know that my conditional statement with the ternary operator works fine, and it is returning a value... but I can't seem to figure out why it isn't returning it back to the filter method...

Does it not work this way? Or do I have to somehow put the forEach with the filter?

Thank you for any help!

Jacob Hornbeck
  • 398
  • 2
  • 19
  • 3
    [forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) returns `undefined` -- I would use [map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) to achieve what I think you want... – Louys Patrice Bessette Nov 12 '20 at 17:50
  • 1
    `.forEach()` doesn't return anything, so your `.filter()` callback returns `undefined`, a falsey value, for each element. Use `.filter(town => towns2get.includes(town.name))` –  Nov 12 '20 at 17:52
  • Oh... I forgot that forEach doesn't return... Thanks! I will try that! – Jacob Hornbeck Nov 12 '20 at 17:55
  • 1
    You possibly will need to use the index within `map`... That is the second argument of the callback you will provide: `towns2get.map((item,index){...}` ;) – Louys Patrice Bessette Nov 12 '20 at 17:58
  • 1
    Does this answer your question? [Why is .forEach returning undefined?](https://stackoverflow.com/questions/53296250/why-is-foreach-returning-undefined) – Louys Patrice Bessette Nov 12 '20 at 18:00
  • @ChrisG - Thanks again! That was the answer I needed! – Jacob Hornbeck Nov 12 '20 at 18:26
  • @LouysPatriceBessette - No, that doesn't answer my question... that just tells me why `.forEach()` returns undefined... which is helpful, but not the answer... Thanks for sharing! – Jacob Hornbeck Nov 12 '20 at 18:35
  • 1
    You're welcome, but it's still a dupe: [How do I check if an array includes a value in JavaScript?](https://stackoverflow.com/questions/237104/how-do-i-check-if-an-array-includes-a-value-in-javascript) (the for loop business is unrelated; turning into a forEach loop was not the solution to the actual problem) –  Nov 12 '20 at 18:44

2 Answers2

2

The better way here is to use the .includes function inside the filter method

const townDataURL = "[some link I probably can't disclose...]"
const towns2get = [
    "Preston",
    "Fish Haven",
    "Soda Springs"
]

fetch(townDataURL)
    .then((response) => {
        return response.json()
    })
    .then((jsonData) => {
        const towns = jsonData["towns"].filter((item) => {
            if(towns2get.includes(item.name) > -1) return true;
            else return false;
        })
        console.log(towns)
    })
Amaarockz
  • 4,348
  • 2
  • 9
  • 27
0

Cris G gave me the answer:

.forEach() doesn't return anything, so your .filter() callback returns undefined, a falsey value, for each element. Use filter(item => towns2get.includes(item.name))Chris G

So the code should then be:

const townDataURL = "[some link I probably can't disclose...]"
const towns2get = [
    "Preston",
    "Fish Haven",
    "Soda Springs"
]

fetch(townDataURL)
    .then((response) => {
        return response.json()
    })
    .then((jsonData) => {
        const towns = jsonData["towns"].filter(item => towns2get.includes(item.name))
        console.log(towns)
    })
Jacob Hornbeck
  • 398
  • 2
  • 19