1

I have the following code within a component called AllJobs

                            <TableCell>
                                    <Link
                                        to={`/job/${item.id}`}
                                        style={{ textDecoration: 'underline', color: 'black' }}
                                    >             
                                     {item.id}
                                    </Link>
                            </TableCell>

When the user clicks on this link, it then calls the component JobDetails as per below route, within my App.js file:

<Router>
  <Switch>
    <Route exact path="/job/:id">
      <JobDetails />
    </Route>
  </Switch>
</Router>

My problem is, within my JobDetails component, I have a useEffect that isn't being fired and unsure why it isn't as I need it to call my getJob() function?

export default function JobDetails() {

const { id } = useParams();

const [currentJob, setCurrentJob] = useState([]);

const getJob = async () => {
    console.log("Inside JobDetails for id:", id)
    try {
      const response = await fetch(`http://localhost:3000/get-job/${id}`);
      const currentJobRec = await response.json();
      console.log("current-job", currentJobRec)
          
      setCurrentJob(currentJobRec);
    } catch (err) {
      console.error(err.message);
    }
  }; 

  useEffect(() => {
    getJob();
  }, []);  

Can anyone please assist as to what I am missing as I need to trigger off the useEffect().

ArthurJ
  • 777
  • 1
  • 14
  • 39
  • Does this answer your question? [ReactJS: useEffect is not run when the url changes](https://stackoverflow.com/questions/60290004/reactjs-useeffect-is-not-run-when-the-url-changes) – pilchard Jun 27 '21 at 13:11

2 Answers2

1

It seems that the way you set up your Routes and Links are very correct. I honestly am not entirely sure what the exact problem is, but I suggest this:

Reruns the effect/getJob() again whenever the id parameter changes: Add id to your dependency array:

useEffect(() => {
    getJob();
  }, [id]);
Bao Huynh Lam
  • 974
  • 4
  • 12
-2

This is the classic gotcha. You can trigger the getJob like this:

// IIFE
useEffect(() => {
    (async () => await getJob())();
}, []); 

Now to the reason, why async call does not work in useEffect ?

First, let's look at useEffect from React docs.

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // Clean up the subscription
    subscription.unsubscribe();
  };
});

Notice, this returns a function (cleanup function). This function is executed when component unmount (incase of empty dependency array).

Now going back to your example

useEffect(() => {
    getJob();
}, []);

getJob is defined as an async function and is therefore bound to return a Promise. Thus instead of cleanup, the Promise is returned causing this mess.

Shravan Dhar
  • 1,455
  • 10
  • 18
  • Appreciate the explanation but unfortunately this still didn't work. The function getJob() is still not being called via useEffect. Could there be something to do with the `link to` route process? – ArthurJ Jun 27 '21 at 12:33
  • I've added `await` in the IIFE. If that does not have any effect still, then check if the `JobDetails` is even being mounted. – Shravan Dhar Jun 27 '21 at 13:06
  • This is not accurate at all. see: [React Hook Warnings for async function in useEffect](https://stackoverflow.com/a/53572588/13762301) for a clean explanation of async in useEffect – pilchard Jun 27 '21 at 13:08
  • @pilchard I'm sorry to inform you that Dan's way is just another way. Both are correct. Imagine you have 5 async calls which you want to trigger inside a `useEffect` and they may even be called in other modules (hence an exported function). Now, do you think it is a good idea defining the whole function in there? Exactly, it isn't. So depending upon the use case we can make the decision. Also, I'll encourage you to not blindly go ahead with the examples you see. React is made to achieve one result by multiple ways. – Shravan Dhar Jun 27 '21 at 13:11
  • Did you read the answer? It also covers using `useCallback()` and adding it to the dependency array. The point is you don't need an IIFE if you've already defined the function either inside or outside the useEffect. Plus the OP's problem is not async related, but route/mount related. – pilchard Jun 27 '21 at 13:14
  • @ShravanDhar - unfortunately your updated solution didn't work either. – ArthurJ Jun 28 '21 at 00:21