1

In my application i want to fetch some user information when i redirect the user to the main page after the login. For this, i use useEffect with an empty array as dependecy so i only get the data when the components first loads. But, for some reason, i only get the data when i reload the main page, not when i get redirected.

login function

export const login = ({ email, password, history }) => {
  return async (dispatch) => {
    try {
      const response = await fetch("http://localhost:5000/api/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          email,
          password,
        }),
      });

      const data = await response.json();
      if (data.status === 200) {
        dispatch(setUser({
          fullname: data.fullname,
          email: data.email
        }));
        localStorage.setItem("userToken", data.user);
        history.push("/");
      } else {
        dispatch(
          setNotification({
            variant: "error",
            message: data.message,
          })
        );
      }
    } catch (e) {
      console.log(e.message);
    }
  };
};

Here is the code i used on the frontend to get the user info

export const fetchUser = () => {
  return async (dispatch) => {
    try {
      const response = await fetch("http://localhost:5000/userInfo", {
        headers: {
          "x-access-token": localStorage.getItem('userToken'),
        },
      });

      const data = await response.json();
      dispatch(
        setUser({
          id: data.id,
          fullname: data.fullname,
          email: data.email,
        })
      );
    } catch (error) {
      console.log(error)
    }
  };

Backend code where i get the token as header and verify it to get the user information

module.exports.getCurrentUser = async (req, res) => {
  const token = req.headers["x-access-token"];
  try {
    const verifyToken = jwt.verify(token, "123");
    const user = await User.findOne({ email: verifyToken.email });
    return res.json({
      id: user._id,
      fullname: user.fullname,
      email: user.email
    })
  
  } catch (error) {
    console.log(error)
  }
};

I´m calling the useEffect inside my app.js

export default function App() {
  const isAuth = isLoggedIn();
  const dispatch = useDispatch();
  const cart = useSelector((state) => state.cart);

  useEffect(() => {
      dispatch(fetchUser());
  }, []);

  useEffect(() => {
    if (!isAuth) {
      return;
    }
    if (isInitial) {
      isInitial = false;
      return;
    }
      if (cart.changed) {
        dispatch(sendCartData(cart));
      }
  }, [cart]);

  return (
    <React.Fragment>
      <Switch>
        <Route path="/" exact>
          <Home />
        </Route>
        <Route path="/componentes" exact>
          <Components />
        </Route>
        <Route path="/login" exact>
          <Login />
        </Route>
        <Route path="/cadastro" exact>
          <Register />
        </Route>
        <Route path="/produto/:nomeProduto" exact>
          <SingleProduct />
        </Route>
        <Route path="/componente/suspensao" exact>
          <Suspension />
        </Route>
        <Route path="/componente/quadro" exact>
          <Frame />
        </Route>
        <Route path="/marca/:brand" exact>
          <Brands />
        </Route>
        <Route path="/carrinho" exact>
          <Cart />
        </Route>
        <Route path="/equipamentos" exact>
          <Equipments />
        </Route>
        <Route path="/acessorios" exact>
          <Accessories />
        </Route>
        <Route path="/casual" exact>
          <Casual />
        </Route>
      </Switch>
    </React.Fragment>
  );
}
Cláudio Vitor Dantas
  • 805
  • 4
  • 10
  • 17

1 Answers1

1

Your <App/> component is not being mounted when the route changes since it is the parent component of the <Switch/>. Thus the useEffect(() => {}, []); does not get fired unless the page is reloaded and the <App/> mounts due to the reload.

Since you have already wrapped this component within a <Router/>, you have access to useLocation() which can be used to fire the fetchUser function whenever the location is changed.

In addition to the below answer, you can force your site to reload when the route changes by adding forceRefresh to your <Router/>. Ex: <Router forceRefresh ></Router>. Here is another answer relating to forceRefresh and a documentation link.

In your case adding the following to the useEffect and imports should be sufficient:


import { useLocation } from 'react-router-dom';

export default function App() {
  const isAuth = isLoggedIn();
  const dispatch = useDispatch();
  // Use the current browser location from router
  const location = useLocation();
  const cart = useSelector((state) => state.cart);

  // Execute your `fetchUser` whenever the route changes
  useEffect(() => {
      dispatch(fetchUser());
  }, [location]);

  useEffect(() => {
    if (!isAuth) {
      return;
    }
    if (isInitial) {
      isInitial = false;
      return;
    }
      if (cart.changed) {
        dispatch(sendCartData(cart));
      }
  }, [cart]);

  return (...);
}

Here is a CodeSandbox demonstration

Edit Forked React Router Demo

HudsonGraeme
  • 399
  • 3
  • 10