Things to avoid
Top React Mistakes
Some useEffect and useState mistakes
https://www.youtube.com/watch?v=GGo3MVBFr1A
Using state when you don’t need state
const [email, setEmail] = React.useState("")
const [password, setPassword] = React.useState("")
function onSubmit(e) {
e.preventDefault();
console.log({email, password})
}
<form>
<label htmlFor="email">Email </label>
<input type="email" id="email" />
... and same for password
</form>Instead (personally I don’t agree with this because according to the react docs, refs should only be used as an escape hatch). Use a ref instead. This might stop your component from unnecessarily re-rendering
const emailRef = useRef()
const passwordRef = useRef()
...
<input ref={emailRef} />Not using function version of useState
const [count, setCount] = useState(0)
function adjustCount(amount) {
setCount(1)
}
...
<button onClick={() => adjustCount(-1)}In setCount remember you can pass in a the current value
setCount(currentCount => {
return currentCount + something
})
If we wanted to do setCount multiple times in row, it won’t use the updated value. So if you want to preserve the current value over each setState, then use the function method
State does not update immediately
Set State doesn’t actually update till the next render.
Set count happens asynchronously so if you try
setCount(...)
console.log(count)Therefore just use a useEffect to track changes.
Referential Equality in UseEffect
If we have a useEffect that has dependencies in it like so
const [age, setAge] = useState(0)
const [name, setName = useState("")
const [darkMode, setDarkMode] = React.useState(false)
// THIS gets reassigned (referencial change) on re-renders!
const person = {age ,name}
useEffect(() => {
console.log(person)
},[person])
...
<input value={age} onChange={e=> setAge(e.target.value}/>
<input type='checkbox' value={darkMode} onChange={e => setDarkMode(e.target.checked)} />When doing the above and toggling the dark mode input checkbox. Person will still be console logged (implying that there is a change in the person object). This is because of referential equality. Every time we change checkbox, the entire component re-renders. This then creates person as a new variable. (basically redefining the object).
In Javascript
const personA = {name: Kevin}
const personB = {name: Kevin}
This is not equalTo get around this use useMemo
const person = useMemo(() => {
return {age, name}
}, [age,name])Person only returns a new object if the dependencies change.
Not aborting fetch requests
useEffect(() => {
setLoading(true)
fetch(url)
.then()
.catch()
.finally()
}, [url])If we change the url a lot, you might get stale data. (Note I think using React Query just solves all of this.
But if we had to implement this. Then using a clean up function would be the way to go
fetch(url, {signal: controller.signal}) ...
...
return () => {
controller.abort()
}