I am trying to perform a state change and after that I want to make an API request. But since useState is asyncronous, I cannot do that. I tried using the useEffect()
hook but it is impossible to find the exact array element that was changed.
In toggleCompleted()
I am getting the old value for updatedTask
because setTasks
is asyncronous.
App.js
import { useState, useEffect } from 'react'
const App = () => {
const [tasks, setTasks] = useState([])
const toggleCompleted = id => {
setTasks(
tasks.map(task => {
return task.id === id
? { ...task, isCompleted: !task.isCompleted }
: task
})
)
// This will get the old value
const updatedTask = tasks.find(task => task.id === id)
// PUT request here
fetch(`${api_url}/tasks/${id}`, {
method: 'PUT',
body: JSON.stringify(updatedTask)
})
}
}
export default App
I also tried using the useEffect
hook, but I am getting the whole tasks
array and not the individual task that was updated so I cannot use this to make a PUT
request to my backend API.
useEffect(() => {
// unable to get the exact one task that was updated
}, [tasks])
CodePudding user response:
You could try to declare updatedTask using useState
hooks as well. And so update its value using setUpdatedTask
const [updatedTask setUpdatedTask] = useState({})
// ...
setUpdatedTask(tasks.find(task => task.id === id))
CodePudding user response:
There are couple of ways you can do this,
- Using
useEffect()
hook with 'useRef()',
as below
import { useState, useEffect, useRef } from 'react'
const App = () => {
const [tasks, setTasks] = useState([])
const idRef = useRef();
const toggleCompleted = id => {
idRef.current = id;
setTasks(
tasks.map(task => {
return task.id === id
? { ...task, isCompleted: !task.isCompleted }
: task
})
)
}
useEffect(() => {
if(idRef.current) {
// PUT request here
fetch(`${api_url}/tasks/${idRef.current}`, {
method: 'PUT',
body: JSON.stringify(tasks.find(task => task.id === idRef.current))
})
}
},[tasks])
}
export default App