1

I have a problem in the following component, it seems that the component doesn't render and I get the following error in console: "Cannot read property 'operationalHours' of null". I don't get why operationalHours it's null.. maybe someone can help me with a posible solution for this issue. Here is the component:

import React, { useState, useEffect } from 'react';
import Search from 'client/components/ui/Search';
import { performSearchById } from 'client/actions/api/search';
import { get } from 'lodash';
import {
  SEARCH_STORE_NOT_CLOSED,
  SEARCH_STORE_OPEN_TEXT,
  SEARCH_STORE_CLOSED_TEXT
} from 'app/client/constants/values';

import DownArrow from 'components/UI/icons/DownArrow';

import styles from './styles.module.scss';

const StoreDetails = ({ storeInfo }) => {
  const [expanded, setIsExpanded] = useState(false);
  const [storeData, setStoreData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      const storeId = storeInfo.store_id;
      const {
        data: {
          Location: {
            contactDetails: { phone },
            operationalHours
          }
        }
      } = await performSearchById(storeId);
      setStoreData({ phone, operationalHours });
    }
    fetchData();
  }, [storeInfo.store_id]);

  const infoText = expanded ? 'Hide details' : 'View details';

  function parseHours(hours) {
    const formattedHours = {};
    hours.forEach(dayObj => {
      const closed = get(dayObj, 'closed', '');
      const day = get(dayObj, 'day', '');
      if (closed === SEARCH_STORE_NOT_CLOSED) {
        const openTime = get(dayObj, 'openTime', '');
        const closeTime = get(dayObj, 'closeTime', '');
        if (openTime === null || closeTime === null) {
          formattedHours[day] = SEARCH_STORE_OPEN_TEXT;
        } else {
          formattedHours[day] = `${openTime}-${closeTime}`;
        }
      } else {
        formattedHours[day] = SEARCH_STORE_CLOSED_TEXT;
      }
    });
    return formattedHours;
  }

  const storeHours = storeData.operationalHours
    ? parseStoreHours(storeData.operationalHours)
    : '';

  return (
    <div className={styles.viewStoreDetails}>
      <span
        className={expanded ? styles.expanded : undefined}
        onClick={() => setIsExpanded(!expanded)}
      >
        <DownArrow />
      </span>
      <div>
        <span className={styles.viewStoreDetailsLabel}>{infoText}</span>
        <div>
          {expanded && (
            <Search
              phoneNumber={storeData.phone}
              storeHours={storeHours}
            />
          )}
        </div>
      </div>
    </div>
  );
};

export default StoreDetails;

3 Answers 3

1

Its because you're setting the values of storeData after the component has already rendered the first time. Your default value for storeData is null.

It breaks here: storeData.operationalHours because null isn't an object and therefore cannot have properties to access on it.

You should probably just set your initial state to something more representative of your actual state:

const [storeData, setStoreData] = useState({}); // Or even add keys to the object.

Also read here about the useEffect hook and when it runs. It seems that the underlying issue is misunderstanding when your data will be populated.

Sign up to request clarification or add additional context in comments.

Comments

0

You are getting error at this line :

    const storeHours = storeData.operationalHours ? 
                 parseStoreHours(storeData.operationalHours): '';

Reason : You initialised storeData as Null and you are trying to access operationalHours key from Null value.

Correct Way is :

Option 1: Initialise storeData as blank object

  const [storeData, setStoreData] = useState({});

Option 2:

  const storeHours =storeData && storeData.operationalHours ? 
                 parseStoreHours(storeData.operationalHours): '';

Comments

0

It's happen because in 1st moment of your application, storeData is null, and null don't have properties, try add a empty object as first value ({}) or access a value like that:

Correct method:

const object = null;
console.log(object?.myProperty);

// output: undefined

Wrong method:

const object = null;
console.log(object.myProperty);

// Generate a error

The Question Mark(?) is a method to hidden or ignore if the variable are a non-object, to decrease verbosity in the code with logic blocks try and catch, in Correct method code there will be no mistake, but in Wrong method code, there will have a mistake.

Edit 1:

See more here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.