-1

So im getting a task by its id, im scanning a barcode i get the id and i get the data of the task, but for some reason i cant setLocation to resultData. Location, when i log resultData i get all the data of the task, when i log resultData.location i get the location object, but when i want to setLocation(resultData.location) i just get an empty object logged - note in use state default state is {}, if i just set the default state to nothing it returns undefined in the console.

    import React, { useContext, useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import BarcodeScannerComponent from 'react-webcam-barcode-scanner';
import axios from '../axios';
import { DashboardContext } from '../contexts/dashboardContext';
import toast from './Notify';
import { database } from '../config/firebase';

const BarcodeReader = ({ setActiveTab, onRequestClose }) => {
  const { setTaskSelected, taskSelected } = useContext(DashboardContext);
  const { isAutoAssign } = useSelector((state) => state.tasks);
  const [location, setLocation] = useState({});
  const [drivers, setDrivers] = useState();
  const [driverLoc, setDriverLoc] = useState([]);
  const [closestDriverID, setClosestDriverID] = useState('')


  const { uid } = JSON.parse(localStorage.getItem('user'));
  const config = {
    headers: {
      Authorization: uid,
    },
  };


  




useEffect(() => {

  (async() => {
    const ref = await database.ref('users');
    ref
      .orderByChild('userType')
      .equalTo('driver')
      .on('value', (snapshotq) => {
        // eslint-disable-next-line no-unused-expressions
        if (snapshotq.val()) {
          setDrivers(snapshotq.exists() && Object.values(snapshotq.val()));
          
        } 
       
      }) 
  }) ()
}, [])
console.log(drivers, "WEEEEE")

console.log(driverLoc,"WEEWFWFW")

useEffect(() => {
  if (drivers !== undefined) {
// {for (let i = 0; i < drivers.length; i++) {

  setDriverLoc(drivers.map((el) => el.lastLocation))
}

}, [drivers])



const distance =  () => {

       
     if (drivers !== null && drivers !== undefined && drivers.length !== 0)
  
    {
      
      
      
     
let lat1 = location?.latitude;
let lon1 = location?.longitude;
let lat2 = driverLoc.map((el) => el.latitude)
let lon2 = driverLoc.map((el) => el.longitude)

    let radlat1 = Math.PI * lat1/180
  let radlat2 = Math.PI * lat2/180
  let theta = lon1-lon2
  let radtheta = Math.PI * theta/180
  let dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
  if (dist > 1) {
      dist = 1;
  }
  dist = Math.acos(dist)
  dist = dist * 180/Math.PI
  dist = dist * 60 * 1.1515
  //  if (unit=="K") { dist = dist * 1.609344 }
  //  if (unit=="N") { dist = dist * 0.8684 }

  for (let i = 0; i < drivers.length; i++) 
{
  
  
  if(dist === drivers[i].lastLocation) {

    setClosestDriverID(drivers[i].uid);

  }}


} else {

  toast.error ('Order location is missing')
}


}
      














  const loadTask = async (taskId) => {
    const { data: resultData } = await axios(
      `order/task/get-by-id/${taskId}`,
      config
    );

    setLocation(resultData.location);
    setTaskSelected(resultData);
    
     
  
      
    console.log('TASK DAAATATAA', Object.keys(resultData));
    console.log('SELECTED', taskSelected)
    console.log('LOCATION', location);
    console.log("DATA LOCATION", resultData.location)
    toast.success('Task loaded');
  };

  const autoAssign = async (taskId) => {
    try {
      
  
      try {
        
        const { data: resultData } = await axios.post(`order/auto-assign/`, {
          taskId: +taskId,
          driverUid: closestDriverID,
        }, config );
        toast.success(resultData.message);
      } catch {
        toast.error(
          'This task is outside the geofence region for this driver'
        );
       
        
      } 
    } catch (error) {
      toast.error('This task is outside the geofence region for this driver');
      loadTask(taskId);
      distance()
      onRequestClose();
    }
  };

  const handleBarcode = (result) => {
    setActiveTab('Dashboard');
    if (!isAutoAssign) {
       loadTask(result);
      distance();
      onRequestClose();
      return;
    }
    try {
      autoAssign(result);
    } catch (error) {
      toast.error('This geofence has more than one driver!');
    }
    onRequestClose();
  };

  return (
    <>
      <BarcodeScannerComponent
        width={800}
        // height={20}
        onUpdate={(err, result) => {
          if (result) handleBarcode(result.text);
        }}
      />
    </>
  );
};

export default BarcodeReader;

This is the call and the logs, here is what i get in console

Can someone explain what is going on and how do i get location? Thanks in advance

Note: i also tried with .then but i got the same results

  • 1
    The log of `location` here won’t reflect the results of setting state until the next tick; setting state is async. Other than that, hard to say without more context. – Dave Newton Nov 01 '21 at 12:47
  • i posted the entire component, please take a look now, thanks – greardrear Nov 01 '21 at 12:49
  • @DaveNewton the log i sent in the screenshot is actually repeated a couple of times when i scan the barcode, and always the location is {} – greardrear Nov 01 '21 at 12:56

1 Answers1

0

The real reason is the execution of setState is asynchronous. So when you console.log the state just after receiving the api response, You can not see the updated state immediately. For more detail explanation, you can checkout this post.

It seems you need the location variable in distance function only, so just return the location in loadTask function and pass it to the distance function is fine.

const handleBarcode = async (result) => {
  setActiveTab('Dashboard');
  if (!isAutoAssign) {
    // Return location in loadTask function
    const {location} = await loadTask(result);
    // Pass it to distance function directly
    distance(location);
    ...
  }
};
bcjohn
  • 2,383
  • 12
  • 27