Why the results of the scripts are different?

40 Views Asked by At

In the first code I need to click one time on the button to present the list of "todo"s and in the second code I need to click twice to present a list of "todo"s.

The difference is inside the getUser and it's a destructuring change.

------1

import React, { useState } from 'react'
import axios from 'axios'

const TODOS_URL = 'https://jsonplaceholder.typicode.com/todos';
const USERS_URL = 'https://jsonplaceholder.typicode.com/users';

const UsersAndTodos = () => {
  const [id, setId] = useState('')
  const [user, setUser] = useState({name: '', email: ''})
  const [TodosTitles, setTodosTitles] = useState([])
  const receiveId = (e) => {
    setId(e.target.value)
  }
  const getUser = async () =>{
    const {data: user} = await axios.get(`${USERS_URL}/${id}`)

    setUser({name: user.name, email: user.email})

    if (user.name.startsWith('E')) {
      const { data: userTodos } = await axios.get(`${TODOS_URL}?userId=${id}`)
      const titles = userTodos.map((todo) => todo.title)
      setTodosTitles(titles)
    } else {
      setTodosTitles([]);
    }
  }

  return (
    <>
    <input type='number' onChange={receiveId}/>
    <button onClick={getUser}>send to data base</button>

    <h1>{id}</h1>
    <h1>{user.name}</h1>
    <h1>{user.email}</h1>
    <br />
    <ul>
      {TodosTitles.map((title,index)=>{
        return <li key={index}>{title}</li>
      })}
    </ul>

    </>  
    
    
  )
}

export default UsersAndTodos

------2
the same as 1 just the change inside getUser:


  const getUser = async () =>{
    const resp = await axios.get(`${USERS_URL}/${id}`)

    setUser({name: resp.data.name, email: resp.data.email})

1

There are 1 best solutions below

0
p7dxb On BEST ANSWER

In your first example:

    const {data: user} = await axios.get(`${USERS_URL}/${id}`)

    setUser({name: user.name, email: user.email})

    if (user.name.startsWith('E')) {
      const { data: userTodos } = await axios.get(`${TODOS_URL}?userId=${id}`)
      const titles = userTodos.map((todo) => todo.title)
      setTodosTitles(titles)
    } else {
      setTodosTitles([]);
    }
  }
  • You set a constant user within this function.
  • So when you get to if (user.name.startsWith('E')) { it can use user from the response constant to go into the if statement
  • This means you only click once
  • In your getUser function I would avoid using the const user as it is confusing with the user in your setState

In your second example:

  const getUser = async () =>{
    const resp = await axios.get(`${USERS_URL}/${id}`)

    setUser({name: resp.data.name, email: resp.data.email})

    if (user.name.startsWith('E')) {
      const { data: userTodos } = await axios.get(`${TODOS_URL}?userId=${id}`)
      const titles = userTodos.map((todo) => todo.title)
      setTodosTitles(titles)
    } else {
      setTodosTitles([]);
    }
  }
  • You are using the user from the useState const [user, setUser] = useState({name: '', email: ''})
  • As setState is asynchronous, when it gets to the if statement on the first click user has not been set
  • When you click the second time the state has been set and so will now go into the if statement

Point to note

  • When you click the second time, you are performing another get request but the user state is likely to still be the value set in the first request