简体   繁体   中英

React-Native - Promises and JSON resolution (undefied)

He,

I am having an intermittent issue with my code where I sometimes get an "undefined" error, leading me to believe that React is trying to process an API request before the JSON is resolved. Can anyone point me in the right direction? How can I ensure that all data is loaded before any processing occurs? (I also had the same issue when using an await function but am happy to use either).

JSON

{"session_details [{"session_index":18,"session_uid":"17249351302794706962","session_date":"2022-06-20","session_notes":null,"session_start_time":"Morning"}],
"clothes_items":[{"clothing_id":36,"category":7,"added_date":"2022-01-25","description":"Gap Jeans","view_front":"99621639896956961_frontview.jpg","view_back":null,"view_360":null,...

React-Native Code:

export function SessionDetails( { route }  ) {
    const { sessionUid } = route.params;

    const [loadingSessionData, setLoadingSessionData] = useState(true);
    const [sessionDetails, setSessionDetails] = useState();
    const [sessionClothes, setSessionClothes] = useState();
    const [sessionGear, setSessionGear] = useState();
    const [sessionTasks, setSessionTasks] = useState();
    const [formattedDate, setFormattedDate] = useState();
    const [currentNote, setCurrentNote] = useState();
    const [saveNotesVisible, setSaveNotesVisible] = useState(false);

function getSessionDetails(sessionUid){
      const url = `${apiUrl}sessions/detail.php?session_uid=${sessionUid}`;
     
      return fetch(url, {
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        }
      }).then((response) => response.json())
    };

    function loadSessionDetails(){
      return Promise.all([getSessionDetails(sessionUid)])
    }

    useEffect(() => {

      setLoadingSessionData(true);
      setSaveNotesVisible(false);

      loadSessionDetails()
        .then(([sessionData]) => {
        
         setSessionDetails(sessionData.session_details[0]);
         setSessionClothes(sessionData.clothes_items);
         setSessionGear(sessionData.gear_items);
         setSessionTasks(sessionData.task_items);
         sessionDetails ? setFormattedDate(moment(sessionData.session_details.session_date).format("dddd, MMMM Do, YYYY.")) : setFormattedDate('There is a problem');
         setCurrentNote(sessionDetails.session_notes);
         setLoadingSessionData(false);
    })

    }, []);

await your Promises, instead of chaining then with them.
return await Promsise.all([...])
Then get the data as
const [data] = loadSessionDetails()

Looks like you are trying to array destructure the response JSON, but you example JSON is not an array.

See if loosing the square brackets in your callback definition helps.

ie instead of

.then(([sessionData]) => {

try

.then((sessionData) => {

In case it helps anyone, this is how I managed to solve it:

async function getSessionDetails(sessionUid){
      const $apiUrl = 'https://apihost.com/api';
      const url = `${apiUrl}sessions/detail.php?session_uid=${sessionUid}`;

      return fetch(url, {
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        }
      }).then((response) => response.json())
        .then(data => {
          // proceed to setup state variables based on the response.
          setSessionDetails(data.session_details[0]);
          sessionDetails ? setFormattedDate(moment(data.session_details[0].session_date).format("dddd, MMMM Do, YYYY")) : setFormattedDate('There is a problem');
          setCurrentNote(data.session_details[0].session_notes);
          // disable LoadingScreen
          setLoadingSessionData(false);
          return
      }).catch(error => {
        console.log(error.message);
        // do some more error handling
      })
    };

    async function loadSessionDetails(){
      // sessionUid is passed into the parent component via route.params
      return await Promise.all([getSessionDetails(sessionUid)])
    }

And the initial useEffect to call the API:

    useEffect(() => {
      setLoadingSessionData(true);
      loadSessionDetails();
    }, []);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM