0
votes

After passing the product ID I'm being redirected to the product details page. In that page, I have details of the product such as name, destination, price and date etc. As I'm using redux and getting the data from mongodb the date is saved as 2021-11-23T18:00:00.000Z this format. So after fetching the data in my product details page I used flight?.data?.date.split("T")[0] to only show the date. But after clicking the button to go to the product details page it shows the following error TypeError: Cannot read properties of undefined (reading 'split'). But when I remove the split part from the code it is working fine. I guess the only reason is the code is running before the data is loaded. So for that I tried to show loading spinner before the data loads by dispatching loading action. But it isn't working. I've used redux thunk for other actions that is why I've added async in Action. Otherwise it gives me dispatch is not defined.

Details page

import { CircularProgress } from "@mui/material";
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useParams } from "react-router-dom";
import { getFlight, loadingStatus } from "../../actions/flights";
import "./Details.css";

const FlightDetails = () => {
  const flight = useSelector((state) => state.flights);
  console.log("flight", flight.loading);

  const dispatch = useDispatch();
  const { id } = useParams();

  useEffect(() => {
    dispatch(loadingStatus(true));
    dispatch(getFlight(id));
    dispatch(loadingStatus(false));
  }, [id, dispatch]);

  return (
    <div className="details_parent">
      {flight.loading ? (
        <CircularProgress />
      ) : (
        <div className="details_container">
          <div className="form_data">
            <span>From</span>
            <h3>{flight?.data?.from}</h3>
          </div>
          <div className="form_data">
            <span>To</span>
            <h3>{flight?.data?.to}</h3>
          </div>
          <div className="form_data">
            <span>Airline</span>
            <h3>{flight?.data?.airline}</h3>
          </div>
          <div className="form_data">
            <span>Trip type</span>
            <h3>{flight?.data?.flightType}</h3>
          </div>
          <div className="form_data">
            <span>Date(yyyy-mm-dd)</span>
            <h3>{flight?.data?.date.split("T")[0]}</h3>
          </div>
          <div className="form_data">
            <span>Price</span>
            <h1>${flight?.data?.price}</h1>
          </div>
        </div>
      )}
    </div>
  );
};

export default FlightDetails;

Reducer

const initialState = {
  data: [],
  loading: false,
};
const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "GET_FLIGHTS":
      return { ...state, data: action.payload };

    case "GET_FLIGHT":
      return { ...state, data: action.payload };

    case "CREATE_FLIGHT":
      return { ...state, data: { ...action.payload } };

    case "SEARCH":
      return { ...state, data: action.payload };

    case "LOADING":
      return { ...state, loading: action.payload };

    default:
      return state;
  }
};

export default reducer;

Actions

export const loadingStatus = (status) => async (dispatch) => {
  dispatch({
    type: "LOADING",
    payload: status,
  });
};
2

2 Answers

0
votes

React runs a first render before running any useEffect calls. Change your initial loading state to true.

const initialState = {
  data: [],
  loading: true,
};
0
votes

why you are not using flight?.data?.date?.split("T")[0]

but in this case you have to set loading in initial data of reducer to true

const initialState = {
  data: [],
  loading: true,
};