Hello,
Here’s the example of PURE Component:
Let’s make it IMPURE:
My Question (Impure Example Photos):
- Why this code not "RESETTING count variable value to 0 ?
let count = 0;
Thank you /\
Hello,
Here’s the example of PURE Component:
Let’s make it IMPURE:
My Question (Impure Example Photos):
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.
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.
Thanks @NJF @sufian.babri /\
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:
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:
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
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
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.
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