Is there a way to check the next location via React Router? I am not interested in using Prompt solution. My goal is to set some condition on component unmount like:
useEffect(() => {
return () => {
if(nextRoute !== '/something') {
resetData();
}
};
}, []);
Is there a way to have a knowledge what is the nextRoute?
Related
I'm trying to update a state as soon as the page comes to focus in react native with react native navigation, but if I log the value it still results in the old one.
useFocusEffect(
React.useCallback(() => {
if (route.params?.key !== null) {
setKey(route.params?.key);
console.log(route.params?.key) //These two console log give different values
console.log(key);
setLastTokenDate(route.params?.date);
}
}, [route.params?.chiave, route.params?.data]),
);
Try this:
useFocusEffect(
React.useCallback(() => {
if (route.params?.key !== null) {
setKey(route.params?.key);
setLastTokenDate(route.params?.date);
}
}, [route.params?.key, route.params?.date]),
);
useEffect(() => {
console.log(key);
}, [key]);
I think you will find where is your mistake
I am having problem rendering ui before redirect in react. I has a variable is called from api, i want to check if it is 'x' then will redirect. But ui will render before redirect.
Bellow is my code:
useLayoutEffect(() => {
getProfile().then((res) => {
setIsLoading(true);
if (res) {
redirectByUserType(res.data.type); // redirect to /home
}
});
}, []);
I tried using useLayoutEffect but not working.
Please help me, thank you so much.
If you don't want to render until getProfile() has finished, then have a state variable which tracks whether it is finished. If it hasn't finished, return null to render nothing. If it has, return whatever you want to render. I would normally call this state variable loading, but you seem to already have one with that name, who's purpose i don't know. Maybe you can piggy back on that, maybe you need a separate one:
const [ready, setReady] = useState(false);
useEffect(() => {
getProfile().then(res => {
setIsLoading(true);
if(res) {
redirectByUserType(res.data.type);
} else {
setReady(true)
}
});
}, []);
if (!ready) {
return null;
}
return (
<div>Something</div>
);
I looked around and tried to find a solution with React router.
With V5 you can use <Promt />.
I tried also to find a vanilla JavaScript solution, but nothing worked for me.
I use React router v6 and histroy is replaced with const navigate = useNavigation() which doesn't have a .listen attribute.
Further v6 doesn't have a <Promt /> component.
Nevertheless, at the end I used useEffect clear function. But this works for all changes of component. Also when going forward.
According to the react.js docs, "React performs the cleanup when the component unmounts."
useEffect(() => {
// If user clicks the back button run function
return resetValues();;
})
Currently the Prompt component (and usePrompt and useBlocker) isn't supported in react-router-dom#6 but the maintainers appear to have every intention reintroducing it in the future.
If you are simply wanting to run a function when a back navigation (POP action) occurs then a possible solution is to create a custom hook for it using the exported NavigationContext.
Example:
import { UNSAFE_NavigationContext } from "react-router-dom";
const useBackListener = (callback) => {
const navigator = useContext(UNSAFE_NavigationContext).navigator;
useEffect(() => {
const listener = ({ location, action }) => {
console.log("listener", { location, action });
if (action === "POP") {
callback({ location, action });
}
};
const unlisten = navigator.listen(listener);
return unlisten;
}, [callback, navigator]);
};
Usage:
useBackListener(({ location }) =>
console.log("Navigated Back", { location })
);
If using the UNSAFE_NavigationContext context is something you'd prefer to avoid then the alternative is to create a custom route that can use a custom history object (i.e. from createBrowserHistory) and use the normal history.listen. See my answer here for details.
I have microfrontend app consisting of two react projects let's call them A and B and if a user clicks a certain link in A project then url is changed. But how can I detect url change in project B. Now I have componentDidUpdate function which checks current location.pathname with previous one. But componentDidUpdate is run only when url is changed within A or B.
componentDidUpdate(prevProps) {
const {
location,
} = this.props;
if (location.pathname.includes('/messages/inbox/') && prevProps.location.pathname !== location.pathname) {
...logic code
}
}
Use reatc-router OR react-router-dom, handle it by useEffect
import { useEffect } from "react";
import { useLocation} from "react-router-dom";
const App = () => {
const location = useLocation();
useEffect(() => {
console.log("Changed");
}, [location.pathname]);
return ();
}
export default App;
You can handle locaton.search instead of location.pathname
You can use history.listen method when trying to detect the route are change.
Docs:
You can listen for changes to the current location using history.listen.
Example :
useEffect(() => {
// To start listening for location changes...
const unlisten = history.listen(({ action, location }) => {
// The current location changed.
});
// Later, when you are done listening for changes
// should have cleanup to remove them
return () => {
unlisten();
};
}, [])
I have a working useEffect to call my google analytics when changing page.
This works fine when changing pages but when you initially load for the first time or refresh it does not call the router.events.on
this is my code
useEffect(() => {
if (cookies === true) {
router.events.on("routeChangeComplete", () => {
ReactGA.pageview(window.location.pathname);
});
return () => {
router.events.off("routeChangeComplete", () => {
ReactGA.pageview(window.location.pathname);
});
};
}
}, [router.events]);
I thought of using an other useEffect to initially call the reactGA but then when changing page it would be called twice, which is not good.
any idea on how to make this work on the initial page load?
That's expected behaviour - router.events is only triggered on client-side page navigations initiated by the Next.js router.
You can call ReactGA.pageview on a separate useEffect to handle initial page loads.
useEffect(() => {
if (cookies === true) {
ReactGA.pageview(window.location.pathname);
}
}, []);