0

In my app, I have a list of university departments. When you click a specific department, you are taken to the department landing page (/department/:deptId). I am using React Router's useParams hook to get the department id from the URL and then find that specific department object from my array of departments passed down as props.

This works fine when navigating from the list of departments to the individual department page, but if I refresh the page, I get the following error: Uncaught TypeError: can't access property "Name", dept is undefined

My code is below:

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';

const Department = props => {
  const { id } = useParams();
  const [dept, setDept] = useState({});

  useEffect(() => {
    const unit = props.depts.find(item => item.Id === Number(id));
    setDept(unit);
  }, [id]);

  return (
    <div>
      <h1>{dept.Name}</h1>
    </div>
  );
};

export default Department;

I'm not sure why this happens. My understanding is that the props should remain the same, and the useEffect should run when the page is refreshed. Any idea what I'm missing?

More code below:

The depts array is passed as props from the App component, which is getting it from an axios call in a Context API component.

import { UnitsContext } from './contexts/UnitsContext';

function App() {
  const { units } = useContext(UnitsContext);

  return (
    <>
      <Navigation />
      <Switch>
        <Route exact path="/" component={Home} />
        <Route exact path="/people" component={Persons} />
        <Route exact path="/department/:id">
          <Department depts={units} />
        </Route>
      </Switch>
    </>
  );
}

// Context Component. Provider wraps `index.js`

export const UnitsContext = createContext();

export const UnitsContextProvider = props => {
  const url = 'http://localhost:5000';

  const [units, setUnits] = useState([]);

  useEffect(() => {
    axios
      .get(`${url}/api/units`)
      .then(res => {
        setUnits(res.data);
      })
      .catch(err => {
        console.log(err);
      });
  }, []);

  return (
    <UnitsContext.Provider value={{ units }}>
      {props.children}
    </UnitsContext.Provider>
  );
};

4
  • Where are depts coming from? When you refresh the page, whole App gets reinitialized. Commented Oct 9, 2020 at 15:14
  • With this part of code it totally should work as dept initial state is {} Commented Oct 9, 2020 at 15:18
  • You may want to consider putting an if statement before your setDept call so you aren't setting the value to undefined if you pass in an id which doesn't exist Commented Oct 9, 2020 at 15:21
  • depts is being passed from the App component, which is where my Department route is declared. App is getting depts from an API call in Context Api. When I put an if statement, it doesn't crash, but I get an empty page on refresh because nothing is being passed. Commented Oct 9, 2020 at 15:53

1 Answer 1

1

the problem is most probably with this,

  useEffect(() => {
    const unit = props.depts.find(item => item.Id === Number(id));
    setDept(unit); // <<
  }, [id]);

Nothing else in ur code sets State except setDept(unit); So, My best guess is props.depth find matches nothing and returns null. Thats why dept.Name results with the error

From MDN,

The value of the first element in the array that satisfies the provided testing function. Otherwise, undefined is returned

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

2 Comments

That seems right. When I console.log(props.depts) in the useEffect, I get the expected array when coming from the lists, but it logs as undefined when I refresh. I'm not sure why this is the case. I'm getting depts from an axios call that I'm doing in a context api component. It's then brought into the App component through a useContext hook. I've edited my original post to include this code
@Rasha whats the initial state of useContext ?

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.