0

Trying to log array elements, I'm getting the following error:

TypeError: Cannot read property '0' of undefined

However, when I CAN log the project.tasks array object in console. But it can't log the elements.

The array seems to exist as I can log the object but NOT the elements. I'm confused. Ideas?

CODE SANDBOX: https://codesandbox.io/s/blissful-mclaren-ll5wo

function EditProjectView(props) {
  const [project, setProject] = useState({});

  // get id from params
  const { id } = useParams();

  // syncronously (same time before and then after) renders it will use this hook
  useLayoutEffect(() => {
    // fake* ajax request to database
    const data = database.projects.find((project) => {
      return project.id == 123;
    }, []);

    setProject(data);
  });

  if (project) {
    return (
      <React.Fragment>
        <main style={classes.content}>
          <div style={classes.projectContainer}>
            <div style={classes.projectOverviewWrapper}>
              <Paper elevation={2}>
                <div style={classes.project}>
                  {/* {<ProjectDetailsView project={project} />} */}
                </div>
              </Paper>
            </div>
            <div style={classes.tasksContainer}>
              <h3>ALL TASKS</h3>
              {console.log(
                "prints out array object successfully i.e. [{..}, {..]]  <-------------",
                project.tasks
              )}
              {console.log(
                "does NOT print array object's elements FAIL <-----------",
                project.tasks[0].taskName
              )}
              <TaskExpansionPanel
                panelTitle={
                  <PanelTitle
                  // totalTimeInMinutes={task.totalTimeInMinutes}
                  // taskNumber={task.taskNumber}
                  // taskName={task.taskName}
                  // taskName={project.projectName}
                  />
                }
                panelDetails={<PanelDescription />}
              />
              <CreateTaskBtn />
            </div>
          </div>
        </main>
      </React.Fragment>
    );
  } else {
    return <p>loading..</p>;
  }
}
3
  • Can you create a codesandbox with the code? Commented Apr 13, 2020 at 11:57
  • Here: codesandbox.io/s/blissful-mclaren-ll5wo Commented Apr 13, 2020 at 12:05
  • Why are you adding console.log statements inside return? Add them before return and inspect what is logging first. Commented Apr 13, 2020 at 12:08

1 Answer 1

1

Try doing this

function printTasks(tasks) {
  if (tasks && tasks.length > 0) {
      return ( console.log(tasks[0].taskName));
  } else {
      return "No tasks found";
  }
}

and then calling this inside your component in place of your current check.

{printTasks(project.tasks)}

What I think happens here is that your fetch from the database isn't done first-time component is painted, so it fails. With this check, it will live to see the second update when data is fetched.

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

6 Comments

That worked! But I don't see how if(project) fails while if(project.tasks && project.tasks.length > 0) renders? ...if a project exists then its tasks property should as well though? Please explain,
project.tasks will be false if an array is empty or non-existent. Even project.tasks.length is maybe redundant
That makes sense. However, project.tasks length is always >0 i'm just database.js (fake data)..you can check the database.js file here: codesandbox.io/s/blissful-mclaren-ll5wo ?
Yes, but it may not be fetched at the moment component is first mounted?
Interesting. So it would mean react renders as the data starts coming in from fetch... instead of waiting for the response completion? Going to research this. Are you sure?
|

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.