Reputation: 575
I am trying to update state with the result of an await axios function, but the state is out of sync by one cycle. Here is the code...
const Index=() => {
const [fileSelected, setfileSelected]=useState(null)
const [uploadId, setuploadId]=useState('')
const [Fred, setFred]=useState('')
const [fileName, setfileName]=useState('')
const [fileType, setfileType]=useState('')
const [uploadPC, setuploadPC]=useState()
const [backendUrl, setbackendUrl]=useState('http://localhost:4000')
useEffect(() => {
console.log("inside useEffect: ", Fred);
}, [Fred]);
const fileHandler=async(e) =>{
try {
let fileSelected = document.getElementById('myfile').files[0]
let fileName = fileSelected.name
let fileType = fileSelected.type
setfileSelected(fileSelected)
setfileName(fileName)
setfileType(fileType)
console.log(fileSelected)
} catch (err) {
console.error(err, err.message)
}
}
const startUpload=async(e) =>{
try {
e.preventDefault()
const params = {
fileName: fileName,
fileType: fileSelected.type
};
let resp = await axios.get(`${backendUrl}/start-upload`, { params })
const { uploadId } = resp.data
console.log(uploadId)// this is all OK
setFred(uploadId)
console.log(Fred)//"This displays the previous cycle: ",
uploadMultipartFile()
} catch (err) {
console.log("startupload ",err)
}
}
const uploadMultipartFile=async() =>{
try {
console.log('Delayed access to the state in here',Fred)
const fileSize = fileSelected.size
const CHUNK_SIZE = 5000000 // 5MB
const CHUNKS_COUNT = Math.floor(fileSize / CHUNK_SIZE) + 1
let promisesArray = []
let start, end, blob
console.log(uploadId)
for (let index = 1; index < CHUNKS_COUNT + 1; index++) {
start = (index - 1) * CHUNK_SIZE
end = (index) * CHUNK_SIZE
blob = (index < CHUNKS_COUNT) ? fileSelected.slice(start, end) : fileSelected.slice(start)
let getUploadUrlResp = await axios.get(`${backendUrl}/get-upload-url`, {
params: {
fileName: fileName,
partNumber: index,
uploadId: Fred,
}
})
etc
The correct uploadId is not available from within uploadMultipartFile which is causing big problems.
I have heard that I should useEffect
, but not sure how to at the moment. I am refactoring from a class and that worked OK
Upvotes: 0
Views: 2078
Reputation: 31315
See if this helps:
Can you move uploadMultipartFile()
out of your component? Let the setState
calls be made from startUpload
.
const startUpload = async (e) => {
try {
// 1 - GATHER NECESSARY PARAMETERS HERE fileName uploadId etc...
// 2 - CALL await uploadMultipartFile(...necessaryParameters)
// 3 - SET NECESSARY STATE AFTER SUCCESSFUL UPLOAD
}
catch {
// HANDLE ERRORS FROM UPLOAD CODE
}
}
Could this solve your problem?
Upvotes: 0
Reputation: 8751
setFred
is an asynchronous method, so you can't get the updated value of Fred
immediately after setFred()
.
setFred(uploadId)
console.log(Fred) // This will console old state value of `Fred`
You should use useEffect
with adding a Fred
dependency to check updated value.
useEffect(() => {
console.log(Fred)
if (Fred) // This means if Fred is not default empty state.
uploadMultipartFile()
}, [Fred])
Upvotes: 2