Project - Animal Fun Facts

Had the same issue.

The reason why it doesn’t display the fact is because your displayFact() is defined after the call inside the loop.

If you move the entire function before the loop it should display correctly!

import { animals } from './animals';
import React from 'react';
import ReactDOM from 'react-dom';


const title = '';

function displayFact(e) {
  // name of the animal the event is targeting
  const animal = e.target.alt;
  // selects the animal from the animals object
  const selectedAnimal = animals[animal];
  // selects a random facts from the facts array inside the animals[animal] object
  const randomIndex = Math.floor(Math.random() * selectedAnimal.facts.length);
  // takes the value of the fact with randomIndex
  const fact = selectedAnimal.facts[randomIndex];
  document.getElementById('fact').innerHTML = fact;
};

const images = [];
for (const animal in animals) {
  images.push(
    <img 
      key={animal}
      className="animal"
      alt={animal}
      src={animals[animal].image}
      arial-label={animal}
      role='button'
      onClick={displayFact}
    />
  );
};
const showBackground = true;
const background = <img 
  className="background"
  alt="ocean"
  src="/images/ocean.jpg" />;

const animalFacts = (
  <div>
    {showBackground && background}
    <div className='animals'>
      {images}
    </div>
    <h1>{title === '' ? 'Click an animal for a fun fact' : title}</h1>
    <p id="fact"></p>
  </div>
);

ReactDOM.render(animalFacts, document.getElementById('root'));
1 Like

I got up to step 8 and the images aren’t appearing as expected. I can barely see the dolphin’s head at the bottom. I think the images are just too big to all show on the screen. Here is my code:

import { animals } from './animals';
import React from 'react';
import ReactDOM from 'react-dom';

const title = '';

const background = <img className='background' alt="ocean" src="/images/ocean.jpg" />

const images = []

for (const animal in animals) {
  images.push(
    <img 
      key={animal}
      className={animal}
      alt={animal}
      src={animals[animal].image}
      ariaLabel={animal}
      role='button'
    />
  )
}

const animalFacts = (
  <div>
    <h1>{title || 'Click an animal for a fun fact'}</h1>
    {background}
    <div className='animals'>
      {images}
    </div>
  </div>
);

ReactDOM.render(animalFacts, document.getElementById('root'))

Not sure if anyone is having this issue, but if you set className to {animal}…set it to ‘animal’ instead. The class should reference an actual class within the stylesheet, not the reference var within the for…in.

Hi everyone!

I’ve just finished Animal Fun Facts project. I had a problem with a displayFact function. Firstly I declared it like this but it didn’t work:

const displayFact = e => {
  const animalName = e.target.alt;
  const facts = animals[animalName]['facts'];
  const factIndex = Math.floor(Math.random()*facts.length);
  const fact = facts[factIndex];
  document.getElementById('fact').innerHTML = fact; 
};

I had watched tutorial on youtube and changed arrow function into function declaration with exactly the same code inside:

function displayFact(e) {
  const animalName = e.target.alt;
  const facts = animals[animalName]['facts'];
  const factIndex = Math.floor(Math.random()*facts.length);
  const fact = facts[factIndex];
  document.getElementById('fact').innerHTML = fact; 
}

Suprisingly for me, it worked.

Probably I missed something on my learning path and I will be grateful if anyone could tell me why arrow function with exactly the same code inside didn’t work?

This happened to me too… wrote a proper arrow function, and it just would not work. Came across this and changed it to a regular function and it worked fine…

It may well have to do with the placement of your arrow function. Did you write the arrow function before or after the for loop? The function declaration works because of hoisting . But function expressions and arrow functions aren’t hoisted, so you need to write your displayFact arrow function before the      for (const animal in animals) { ...      loop.

Try experimenting and running the following examples:

greet()

function greet() {
    console.log("Hello!")
}

// This works because a function declaration has been used to declare greet.
// Even though the function declaration is below the function call, 
// it works because the entire function declaration is hoisted.
greet()

const greet = function() {
    console.log("Hello!")
}

// ReferenceError: Cannot access 'greet' before initialization
greet()

const greet = () => {
    console.log("Hello!")
}
// ReferenceError: Cannot access 'greet' before initialization

With the above in mind,

// This won't work
for (const animal in animals) {
    ...
    onClick={displayFact}
    ...
}

const displayFact = e => { ... }

______________________________
// This will work
const displayFact = e => { ... }

for (const animal in animals) {
    ...
    onClick={displayFact}
    ...
}

With a function declaration, it doesn’t matter whether the function declaration comes before or after the loop, because the entire function declaration will be hoisted.