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 equal

To 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()
}