7

I am running a React application.

When I enter the page through routes(click button or link) page works fine but when I reload the page it crashes. I cannot see where the error is, the console and source show just blank, this is the server message console message.

server: Entrypoint index [big] = index.js index.1af9d975ff74be4d27d9.hot-update.js index.c93bf08301ec20c0dc85.js.map index.c93bf08301ec20c0dc85.js.map
server:    533 modules
server: backend debug read session { csrfToken: '0ae87c36d850008df20b58941bf89072', id: 2 }
server: backend debug {"data":{"currentUser":null}} <= undefined
server: backend debug {"data":{"currentUser":null}} <= undefined
server: backend debug read session {}
server: backend error TypeError: Cannot convert undefined or null to object
server:     at getPrototypeOf (<anonymous>)
server:     at hoistNonReactStatics (/Users/apple/Desktop/dev/bethabit/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js:71:38)
server:     at resolveComponent (/Users/apple/Desktop/dev/bethabit/node_modules/@loadable/component/dist/loadable.cjs.js:332:3)
server:     at InnerLoadable.loadSync (/Users/apple/Desktop/dev/bethabit/node_modules/@loadable/component/dist/loadable.cjs.js:189:24)
server:     at new InnerLoadable (/Users/apple/Desktop/dev/bethabit/node_modules/@loadable/component/dist/loadable.cjs.js:138:17)
server:     at processChild (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3048:14)
server:     at resolve (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3013:5)
server:     at ReactDOMServerRenderer.render (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3436:22)
server:     at ReactDOMServerRenderer.read (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3395:29)
server:     at renderToStaticMarkup (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3969:27)
server:     at process (/Users/apple/Desktop/dev/bethabit/node_modules/@apollo/react-ssr/lib/react-ssr.cjs.js:38:16)
server:     at process._tickCallback (internal/process/next_tick.js:68:7)
server: backend debug read session { id: 3 }
server: backend debug loading <= currentUser
server: backend debug loading <= currentUser
server: backend debug loading <= currentUser
server: backend debug {"data":{"currentUser":{"id":3,"username":"[email protected]","role":"user","isActive":true,"email":"[email protected]","__typename":"User"}}} <= currentUser
server: backend debug {"data":{"currentUser":{"id":3,"username":"[email protected]","role":"user","isActive":true,"email":"[email protected]","__typename":"User"}}} <= currentUser
server: backend debug {"data":{"currentUser":{"id":3,"username":"[email protected]","role":"user","isActive":true,"email":"[email protected]","profile":{"firstName":"Caner","lastName":"Çakmak","fullName":"Caner Çakmak","__typename":"UserProfile"},"auth":{"certificate":null,"facebook":{"fbId":null,"displayName":null,"__typename":"FacebookAuth"},"google":{"googleId":"104801577244556473676","displayName":"Caner Çakmak","__typename":"GoogleAuth"},"github":null,"linkedin":null,"__typename":"UserAuth"},"__typename":"User"}}} <= currentUser
server: backend debug read session {}
server: backend error TypeError: Cannot convert undefined or null to object
server:     at getPrototypeOf (<anonymous>)
server:     at hoistNonReactStatics (/Users/apple/Desktop/dev/bethabit/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js:71:38)
server:     at resolveComponent (/Users/apple/Desktop/dev/bethabit/node_modules/@loadable/component/dist/loadable.cjs.js:332:3)
server:     at InnerLoadable.loadSync (/Users/apple/Desktop/dev/bethabit/node_modules/@loadable/component/dist/loadable.cjs.js:189:24)
server:     at new InnerLoadable (/Users/apple/Desktop/dev/bethabit/node_modules/@loadable/component/dist/loadable.cjs.js:138:17)
server:     at processChild (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3048:14)
server:     at resolve (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3013:5)
server:     at ReactDOMServerRenderer.render (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3436:22)
server:     at ReactDOMServerRenderer.read (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3395:29)
server:     at renderToStaticMarkup (/Users/apple/Desktop/dev/bethabit/node_modules/react-dom/cjs/react-dom-server.node.development.js:3969:27)
server:     at process (/Users/apple/Desktop/dev/bethabit/node_modules/@apollo/react-ssr/lib/react-ssr.cjs.js:38:16)
server:     at process._tickCallback (internal/process/next_tick.js:68:7)

this is the code that runs. I tried removing currentuser, addhabit and many other things to just to understand where the error comes from. No results. Everything works fine if I enter the page through a link.

HabitaddView.web.jsx

const HabitAddView = ({ addHabit, t, currentUser }) => {
  const renderMetaData = () => (
    <Helmet
      title={`${settings.app.name} - ${t('habit.title')}`}
      meta={[
        {
          name: 'description',
          content: t('habit.meta')
        }
      ]}
    />
  );
  return (
    <PageLayout>
      {renderMetaData()}
      <div className="row">
        <div className="col-sm-12 padTop10">
          <h2>{t(`habit.label.create_new`)}</h2>
        </div>
      </div>
      <HabitForm onSubmit={onSubmit(addHabit)} currentUser={currentUser} />
    </PageLayout>
  );
};

HabitForm.web.jsx

const HabitForm = ({ values, handleSubmit, setFieldValue, submitting, t  }) => {
  const [habitType, sethabitType] = useState('Fitness Habits');
  const [intervalText, setIntervalText] = useState(t('habit.field.interval'));

  const [habitActions, sethabitActions] = useState([]);
  const [habitFreqs, sethabitFreqs] = useState([]);
  const [habitDurations, sethabitDurations] = useState([]);
  const [habitIntervals, sethabitIntervals] = useState([]);

  const [showInterval, setshowInterval] = useState(true);
  const [showHabitDiv, setshowHabitDiv] = useState(false);

  const [habitActionDisabled, sethabitActionDisabled] = useState(true);
  let calendarComponentRef = React.createRef();
  let calendarWeekends = true;
  let [calendarEvents, setCalendarEvents] = useState([]);

  var timeZones = moment.tz.names();

  const handleHabitTypeChange = (type, value, setFieldValue) => {
    setFieldValue(type, value);
    resetValues();
    Object.values(settings.habits.list).map(object => {
      if (object.habit_type == value) {
        const _habitActions = [];
        Object.values(object.habit_actions).map(object2 => {
          _habitActions.push(object2.title);
        });
        sethabitType(value);
        sethabitActions(_habitActions);
        setshowHabitDiv(false);
        sethabitActionDisabled(false);
      }
    });
  };

  const updateIntervalText = worktype => {
    if (worktype === 5) {
      setIntervalText(t('habit.field.number'));
    } else if (worktype === 6 || worktype === 7) {
      setIntervalText(t('habit.field.proof'));
    } else {
      setIntervalText(t('habit.field.interval'));
    }
  };

  const handleHabitActionChange = (type, value, setFieldValue) => {
    const preparedValue = Array.isArray(value) ? value[0] : value;
    setFieldValue(type, preparedValue);
    const _habitFreqs = [];
    const _habitDurations = [];
    const _habitIntervals = [];
    resetValues();
    Object.values(settings.habits.list).map(object => {
      if (object.habit_type == habitType) {
        Object.values(object.habit_actions).map(object2 => {
          if (object2.title == preparedValue) {
            Object.values(object2.duration).map(object4 => {
              _habitDurations.push(object4);
            });
            Object.values(object2.interval).map(object5 => {
              _habitIntervals.push(object5);
            });
            sethabitFreqs(_habitFreqs);
            sethabitIntervals(_habitIntervals);
            sethabitDurations(_habitDurations);
            setshowHabitDiv(true);
            setFieldValue('timezone', moment.tz.guess());
            setFieldValue('worktype', object2.worktype);
            setFieldValue('description', object2.description);
            setFieldValue('misc', JSON.stringify(object2.misc));
            updateIntervalText(object2.worktype);
          }
        });
      }
    });
  };

  const handleValueChange = (type, value, setFieldValue) => {
    const preparedValue = value;
    setFieldValue(type, preparedValue);
    let timezone = values.timezone;
    let interval = values.interval;
    let duration = values.duration;
    if (type === 'timezone') {
      timezone = value;
    } else if (type === 'interval') {
      interval = value;
    } else if (type === 'duration') {
      duration = value;
    }
    updateCalendarEvents(values.habit_action, timezone, interval, duration);
  };

  const empty = e => {
    switch (e) {
      case '':
      case 0:
      case '0':
      case null:
      case false:
      case typeof this == 'undefined':
        return true;
      default:
        return false;
    }
  };

  const resetValues = () => {
    values.duration = '';
    values.interval = '';
    values.timezone = '';
    updateCalendarEvents(values.habit_action, values.timezone, values.interval, values.duration);
  };

  const updateCalendarEvents = (habit_action, timezone, interval, duration) => {
    setCalendarEvents([]);
    let events = [];
    if (!empty(timezone) && !empty(interval) && !empty(duration)) {
      var dur = JSON.parse(duration);
      var int = JSON.parse(interval);
      var times = dur.count;
      var counter = 0;
      for (var i = 0; i < times; i++) {
        if (i % int.step === 0) {
          counter += 1;
          var obj = {
            title: values.habit_action + ' ' + int.title,
            start: moment
              .tz(values.timezone)
              .add(i + 1, 'days')
              .format(),
            allDay: true
          };
          let addObj = true;
          if (values.worktype === 7 && i === 0) {
            addObj = false;
          }
          if (dur.weekdays === true && (moment(obj.start).isoWeekday() === 6 || moment(obj.start).isoWeekday() === 7)) {
            addObj = false;
          }
          if (
            values.worktype === 7 &&
            counter > 2 &&
            counter < 10 &&
            (habit_action === 'Stay Alcohol Free' || (habit_action === 'Stay Nicotine Free' && dur.count === 28))
          ) {
            obj.start = moment
              .tz(values.timezone)
              .add(i + (counter - 1), 'days')
              .format();
            true;
          }
          if (addObj) {
            events.push(obj);
          }
        }
      }
      if (habit_action === 'Stay Alcohol Free' && dur.count === 28) {
        events.sort(function(a, b) {
          return moment(b.start) - moment(a.start);
        });
        events.shift();
        events.shift();
      }
      setCalendarEvents(events);
    }
  };
  if (settings.habits.list) {
    return (
      <div className="row">
        <div className="col-sm-5">
          <div className="card">
            <div className="card-body">
              <Form name="habit" onSubmit={handleSubmit}>
                <Field
                  name="habit_type"
                  component={RenderSelect}
                  type="select"
                  label={t('habit.field.habit_type')}
                  value={values.habit_type}
                  onChange={value => handleHabitTypeChange('habit_type', value, setFieldValue)}
                  cols={1}
                >
                  <Option value={0}>--Please Select--</Option>
                  {Object.values(settings.habits.list).map((object, i) => {
                    return (
                      <Option key={i} value={object.habit_type}>
                        {object.habit_type}
                      </Option>
                    );
                  })}
                </Field>

habitadd.jsx

class HabitAdd extends React.Component {
  static propTypes = {
    currentUser: PropTypes.object
  };

  constructor(props) {
    super(props);
    this.subscription = null;
    this.state = { options: [] };
  }

  render() {
    if ( this.props.currentUser) {
      return <HabitAddView {...this.props} />;
    } else {
      return <div></div>;
    }
  }
}

export default compose(
  graphql(ADD_HABIT, {
    props: ({ ownProps: { history, navigation }, mutate }) => ({
      addHabit: async (
        habit_type,
        habit_action,
        duration,
        interval,
        timezone,
        description,
        worktype,
        misc,
        user_id
      ) => {
        let habitData = await mutate({
          variables: {
            input: {
              habit_type: habit_type,
              habit_action: habit_action,
              duration: duration,
              interval: interval,
              timezone: timezone,
              description: description,
              worktype: worktype,
              misc: misc,
              user_id: user_id
            }
          },
          optimisticResponse: {
            __typename: 'Mutation',
            addHabit: {
              __typename: 'Habit',
              id: null,
              habit_type: habit_type,
              habit_action: habit_action,
              duration: duration,
              interval: interval,
              timezone: timezone,
              description: description,
              worktype: worktype,
              misc: misc,
              user_id: user_id,
              days: [],
              bets: []
            }
          }
        });

        if (history) {
          window.location.href = window.location.origin + '/habit/' + habitData.data.addHabit.id;
        } else if (navigation) {
          return navigation.push('HabitEdit', { id: habitData.data.addHabit.id });
        }
      }
    })
  }),
  graphql(CURRENT_USER_QUERY, {
    props({ data: { error, currentUser } }) {
      if (error) throw new Error(error);
      return { currentUser };
    }
  })
)(HabitAdd);

Thanks to Ace, I realized my mistake. Added this code line on habitAdd render method

render() {
    if ( this.props.currentUser) {
      return <HabitAddView {...this.props} />;
    } else {
      return <div></div>;
    }
  }
4
  • Can you please check const HabitAddView = ({ addHabit, t, currentUser }) => { whether your props got currentUser property or not? Commented Nov 27, 2019 at 15:34
  • yes they have. HabitAddView.propTypes = { addHabit: PropTypes.func.isRequired, currentUser: PropTypes.object, t: PropTypes.func }; Commented Nov 28, 2019 at 16:04
  • It looks that until some point you don't have currentUser yet. If you component relies on the current user, then you should render empty state of the component or not render the component in the parent component. Then, when current user will be loaded, the component will be rendered properly. Commented Dec 3, 2019 at 22:36
  • try to add a default value to currentUser Commented Dec 5, 2019 at 3:06

3 Answers 3

3
+50

The issue is with the currentUser. Consider initializing it. Before routing I am assuming you are setting the value for the currentUser or the currentUser is being set to a value, but on refresh, the value is reset, though the component will load, the value for currentUser isn't available hence the error.

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

4 Comments

how do I initialize on refresh? everything works on routing..
you need to initialize currentUser to maybe an empty string. So during the routing flow, the relevant value will be assigned to it. On refresh, the store is reset to the initial state, since you currentUser is initial, you would not face this issue.
thank you, I solved it by rendering an empty div just before the current user loads
yes, the conditional rendering also fixes the issue :)
0

VSCode is helpful here. Try running the node app in debug mode with --inspect option, with Pause on Exceptions option checked.

Alternatively you could look into configuring your app to have longer stack traces, or use something like longjohn [https://www.npmjs.com/package/longjohn] that aids with that.

Comments

0

It happened when inlineRequires are enabled in metro.config.js. Try disabling it and run the build again...

module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: true,
        inlineRequires: false
      }
    })
  }
};

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.