1

I am learning the react hooks and i used the random API for fetching the demo users. can anyone told me why the hello is printed 6 times and also i am not able to use the if statement inside my return statement

import React, {useState, useEffect} from "react";

function RandomUser () {
    const [users, setuser] = useState([]);
    const [loading, setLoading ] = useState(true);

    useEffect(()=>{
        console.log("fetching api ");
        fetch("https://randomuser.me/api/?results=50").then((res)=>{
            return res.json();
        }).then((res)=>{
            setuser(res.results);
            setLoading(false);
        })
    },[])
        console.log("hello");
    return (
        <>
        {loading && <h1>Loading</h1>}
        {users.map((v,i)=>{
            return(
                <li>
                    {v.name.first}
                </li>
            )
        })}
        </>
    );
}

export default RandomUser;

enter image description here

I am getting Expression expected error

Night owl
  • 145
  • 10

1 Answers1

4

Your console.log line is not inside your useEffect hook, and therefore is being called every render. React calls render whenever it needs to, so you should not include code that has side effects (except for hooks) inside of functional components. If you want that log line to be called after you get a result back, then move it up to after setLoading(false);

JSX does not support if statements inside JSX literals, but it does support ternary expressions (condition ? trueValue : falseValue) and boolean expressions (condition && trueValue or condition || falseValue), which usually work. Alternatively, you can put your if blocks in small subcomponents, or in helper functions. Just make sure that you always return either a component or null from every branch of code. For example to make a loading component:

function Loading ({loading=true}) {
  if (loading) return (<h1>Loading...</h1>)
  return null // notice the else is not necessary here
}

//and use it like this:

return(<><Loading loading={loading} /></>)

The reason why if statements aren't supported is that they don't have return values (they aren't expressions), while ternary and boolean expressions do. You can call return from inside an if statement, but that causes the whole function to return, not just the if statement.

JSX gets complied to something like React.createComponent(React.Fragment, null, children). Imagine what would happen if you put an if statement where children is. In fact, try something like console.log(if (true) {true} else {false}) and see what happens. It fails because you have to provide an expression, not a statement as an argument to a function. (Note though that generally an expression is also a statement, but not always the other way around).

You may find this video helpful: https://en.hexlet.io/courses/intro_to_programming/lessons/expressions/theory_unit

Garrett Motzner
  • 3,021
  • 1
  • 13
  • 30