skip to Main Content

I’m in the process of creating a React Native application for the first time.

I have made a JourneyScreen component, which will be used to display directions to a destination. I am making a call to my API which will return the directions, but as i am currently test driving this component, the result of the API call is mocked, and i can see it is mocking the result just fine, so i have no concerns about the axios request just yet.

My problem is that when i call setDirections, i am not convinced that the value is being changed.

import React, { useEffect, useState } from 'react';
import { Button, Text, View, TouchableOpacity } from 'react-native';
import axios from 'axios';
import Leg from './leg';

export default function JourneyScreen({
  navigation,
  startLocation,
  endLocation,
}) {
  const [directions, setDirections] = useState({});

  useEffect(() => {
    console.log('Directions: ', directions);
  }, [directions]);

  useEffect(() => {
    const getDirections = async (startLocation, endLocation) => {
      const result = await axios.get('https://localhost:3000');
      console.log('result: ', result);
      setDirections(result);
    };

    getDirections(startLocation, endLocation);
  }, [startLocation, endLocation]);

  return (
    <>
      <Text>{`Directions: ${directions}`}</Text>
      <Text>Directions</Text>
      <Leg />
    </>
  );
}

When i console.log result in the useEffect, i am getting the API reponse that is expected.

When i console.log the contents of directions in my return block, i can see that it is still just an empty object, meaning it has not been set to the contents of result.

EDIT i’ve added a useEffect just to keep track of and log directions and am still getting the same result.

Does anyone have any idea as to why that is?

3

Answers


  1. Since you did not share the way you debug. I believe this is an asynchronous issue.

    useState does not work synchronously, you need to wait to listen to this change.

    Also in your code, you’re using async but in calling the function you’re not waiting for the function.

    So you need to put await.

    If you want to check the directions state, you can listen with useEffect like this:

      React.useEffect(() => {
        console.log('Directions: ', directions);
      }, [directions]);
    
    

    So whenever the value of the direction is changed, you can listen to the changed value.

    However, always keep in mind that asynchronous functions/behaviour etc.

    Edit:
    I also noticed that {console.log('directions: ', directions)} value in your code but you should not put the console.log inside the JSX.

    You can do instead:
    <Text>{`Directions: ${directions}`}</Text>

    If I misunderstood your question, please tell me so we can deep dive into it 🙂

    Login or Signup to reply.
    1. Your code won’t work because you try to render console log return. If you want to inspect the value you can log right before return value and it will be called after each component render, or you can do additional useEffect listening on directions and logging the value after each change.
    2. Pls use try-catch if you call api somewhere 😉
    Login or Signup to reply.
  2. useState setter functions update the state asynchronously. You are never guaranteed that the next line after the setter will have the updated value.

    You can always subscribe to updates to a variable using useEffect to perform actions on change of the value by using it in the dependency array

    const [val, setVal] = 0;
    
    useEffect(() => {
     // function will trigger when val has been updated to new value
    }, [val])
    
    const incrementVal = () => {
      setVal(val + 1);
      
      console.log(val) // probably still updating because it is asynchronous, will most likely show old value
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search