About Pure component, why count variable is not resetting to 0?

Hello,

Here’s the example of PURE Component:
1


3

Let’s make it IMPURE:
4
5

My Question (Impure Example Photos):

  1. Why this code not "RESETTING count variable value to 0 ?
    let count = 0;

Thank you /\

Because ‘let count = 0’ is in the Message.tsx file,
but not in the Message component (const Message = () => {}).
So rendering the Message component a few times in App.tsx doesn’t call the statement ‘let count = 0’ but only the Message component stuff.
Technically speaking, the ‘let count=0’ assignment is outside the scope of the Message component.

1 Like

NJF is right.

I must also add that your component is NOT pure as it depends on a variable outside its scope (its scope is the function you’ve defined as:

const Message = () => ...

Read more about pure components in React Docs.

1 Like

Thanks @NJF @sufian.babri /\

  1. When is “let count = 0;” executed ?
  2. How many times is “let count = 0;” executed ?

Thank you so much for your help
It means a lot for me /\

The line let count = 0 is run once the file Message.tsx is loaded.

What you need to do is the following:

  1. From your App component, you will pass the “count” as prop to your Message component
  2. The Message component will show the value of the count.

App.tsx will be like this:

function App() {
	return (
		<div>
			<Message count={1} />
			<Message count={2} />
			<Message count={3} />
		</div>
	);
}

Message.tsx will look like this:

type Props = { count: number }

const Message = ({ count }: Props) => {
    return <div>Message {count}</div>
}

export default Message;

Hi @sufian.babri Noted. Thank you

Maybe I could try to “console.log()” to find the answer about these:

  1. When is “let count = 0;” executed ?
  2. How many times is “let count = 0;” executed ?

Thank you /\

Yes that’s a good way to go about, but I’d mention that writing any code directly inside the component will get executed every time your component re-renders.

So if you do count++ in your Message component like below, the count will be incremented every time React decides to re-render the Message component (React thinks that something has changed and that it might need to update the UI):

let count = 0;

const Message = () => {
    count++;

    return <div>Message {count}</div>
}

export default Message;

Hi @sufian.babri Noted. Thanks.

I’m stuck with “Creating data”, could you please give me a pointer,
why when creating data using “setUsers()” below, even calling “setUsers()” twice, why still users array on consist one “name: mosh” ?

here’s the code:

const addUser = () => {
    const originalUser = [...users]
    const newUser = { id: 0, name: 'Mosh' }
    setUsers([newUser, ...users]) // 1st call

    userService
      .create(newUser)
      .then(({ data: savedUser }) => {
        setUsers([savedUser, ...users])   // 2nd call
      })
      .catch((err) => {
        setError(err.message)
        setUsers(originalUser)
      })
  }

The end result should be like this right:

[
   {id:  0, 'Mosh'},
   {id: 11, 'Mosh'}
]

but why the result is:

[
   {id: 11, 'Mosh'}
]

Thanks your your help /\

Can you share more code? Mosh is using Class Components in the course and it looks like you’re using React Hooks (e.g. useState).

Hello @sufian.babri

Sure.
Here’s the full code. (only App.tsx, no others):

import axios, { CanceledError } from 'axios'
import { useEffect, useState } from 'react'

interface User {
  id: number
  name: string
}

function App() {
  const [users, setUsers] = useState<User[]>([])
  const [error, setError] = useState('')
  const [loading, setLoading] = useState(false)

  const deleteUser = (user: User) => {
    const originalUsers = [...users]
    setUsers(users.filter((u) => u.id !== user.id))

    axios
      .delete(`https://jsonplaceholder.typicode.com/users/${user.id}`)
      .catch((err) => {
        setError(err.message)
        setUsers(originalUsers)
      })
  }

  const addUser = () => {
    const originalUser = [...users]
    const newUser = { id: 0, name: 'Mosh' }
    setUsers([newUser, ...users])

    axios
      .post('https://jsonplaceholder.typicode.com/users', newUser)
      .then(({ data: savedUser }) => setUsers([savedUser, ...users]))
      .catch((err) => {
        setError(err.message)
        setUsers(originalUser)
      })
  }

  useEffect(() => {
    const controller = new AbortController()

    setLoading(true)
    axios
      .get<User[]>('https://jsonplaceholder.typicode.com/users', {
        signal: controller.signal,
      })
      .then((res) => {
        setUsers(res.data)
        setLoading(false)
      })
      .catch((err) => {
        if (err instanceof CanceledError) return
        setError(err.message)
        setLoading(false)
      })

    return () => controller.abort()
  }, [])

  return (
    <>
      {error && <p className="text-danger">{error}</p>}
      {loading && <div className="spinner-border"></div>}
      <button className="btn btn-primary mb-3" onClick={addUser}>
        Add
      </button>
      <ul className="list-group">
        {users.map((user) => (
          <li
            key={user.id}
            className="list-group-item d-flex justify-content-between"
          >
            {user.name}
            <button
              className="btn btn-outline-danger"
              onClick={() => deleteUser(user)}
            >
              Delete
            </button>
          </li>
        ))}
      </ul>
    </>
  )
}

export default App

Yes, not using class. It’s mosh’s new react course, titled: “React 18 for Beginners”

Thank you

  1. Please see the code below, that I put some “console.log()”:
import axios, { CanceledError } from 'axios'
import { useEffect, useState } from 'react'

interface User {
  id: number
  name: string
}

function App() {
  const [users, setUsers] = useState<User[]>([])
  const [error, setError] = useState('')
  const [loading, setLoading] = useState(false)

  const deleteUser = (user: User) => {
    const originalUsers = [...users]
    setUsers(users.filter((u) => u.id !== user.id))

    axios
      .delete(`https://jsonplaceholder.typicode.com/users/${user.id}`)
      .catch((err) => {
        setError(err.message)
        setUsers(originalUsers)
      })
  }

  const addUser = () => {
    const originalUser = [...users]
    const newUser = { id: 0, name: 'Mosh' }
    setUsers([newUser, ...users])
    console.log('after calling 1st setUsers(), users =', users)

    axios
      .post('https://jsonplaceholder.typicode.com/users', newUser)
      .then(({ data: savedUser }) => {
        console.log('before calling 2nd setUsers(), users =', users)
        setUsers([savedUser, ...users])
        console.log('after calling 2nd setUsers(), users =', users)
      })
      .catch((err) => {
        setError(err.message)
        setUsers(originalUser)
      })
  }

  useEffect(() => {
    const controller = new AbortController()

    setLoading(true)
    axios
      .get<User[]>('https://jsonplaceholder.typicode.com/users', {
        signal: controller.signal,
      })
      .then((res) => {
        setUsers(res.data)
        setLoading(false)
      })
      .catch((err) => {
        if (err instanceof CanceledError) return
        setError(err.message)
        setLoading(false)
      })

    return () => controller.abort()
  }, [])

  console.log('users =', users)

  return (
    <>
      {error && <p className="text-danger">{error}</p>}
      {loading && <div className="spinner-border"></div>}
      <button className="btn btn-primary mb-3" onClick={addUser}>
        Add
      </button>
      <ul className="list-group">
        {users.map((user) => (
          <li
            key={user.id}
            className="list-group-item d-flex justify-content-between"
          >
            {user.name}
            <button
              className="btn btn-outline-danger"
              onClick={() => deleteUser(user)}
            >
              Delete
            </button>
          </li>
        ))}
      </ul>
    </>
  )
}

export default App
  1. here’s the output of console.log() after clicking “Add Button” ONCE:
  • you see that the users data “after calling 1st setUsers()”, total = 11. means that “name: Mosh” is successfully added to users array and users array has 11 names.

  • see that the users data “before calling 2nd setUsers()”, users = 10. how come ? it supposed to be 11 right ?

Thank you

It is not working like you expect because React updates the state after about 16 ms. So, to observe changes, you can use the useEffect hook.

Write the following code after the line const [loading, setLoading] = useState(false):

useEffect(() => console.log("users", users), [users]);

PS: I haven’t started this course yet, but I guess useEffect will be covered later on in the course.

hi @sufian.babri

I made a separate post about this question,
you can see this link: Why "setUsers([savedUser, ...users])" not make "name: Mosh" twice instead of one only? - #5 by Jorge