componentWillReceiveProps in React Native vs ReactJS - javascript

I am in the process transferring my React Webapp to a React Native version.
In React Native, I have this in the login page. I am using react-navigation.
componentWillReceiveProps(nextProps) {
const { requestStatus, currentUser } = nextProps
const getUserInProgress = get(requestStatus, GET_MY_DETAILS, true)
if (!getUserInProgress) {
if (currentUser) {
currentUser.verified_mobile ? this.props.navigation.navigate('Dashboard') : this.props.navigation.navigate('VerifyMobile')
} else if (!currentUser) {
console.log('not logged in')
}
}
}
So on the login page, it gets the user details and check if mobile is verified and then if it isn't, goes to verify mobile page.
On the verify mobile page, when a call is made, this componentWillReceiveProps on the login page still runs even though it's not the current active page.
I have the same logic/code in ReactJS and it behaves totally different.
Is this normal for React Native?
Edit:
Let me clarify what my problem is.
When I am not on the login page and I am on the verify mobile page. The componentWillReceiveProps is still running despite that page is in the history. This did not happen when I built the reactjs app. It is only happening in the react native app. So I'm wondering if this is normal behavior for pages in the history stack to run its componentWillReceiveProps?

The function still executes in react-native because it is still active in the stack while in react app, only the displayed page is active so functions in other pages are 'disabled' in a sense.

Related

How to Render a React Component incase of offline state using service worker?

I have a React component OfflinePage.js and HomePage.js, in case of offline state, i want to render OfflinePage using service-worker but not through react conditional rendering, this OfflinePage should render when offline-state -> refresh page, currently i have a LostConnection.js which render when offline through React Conditional rendering and it has a TryAgain button which refreshes the page, i want to render the OfflinePage when i refresh the page on LossConnection state and no internet coverage using service-worker.
i tried this using offlinepage.html instead of OfflinePage.js, it is working fine but when i converted this html page(offlinepage.html) to React Component (OfflinePage.js), it is not redirecting to OfflinePage.js when offline state.

useLocation hook keeps states even on hard refresh

While working on a project I noticed a weird behavior of the useLocation hook that I can`t find an explanation to.
I have a button that when clicked it will redirect you to an EditOrder page and will pass a state with it:
const navigate = useNavigate();
const handleClick = (data) => {
navigate("edit-order", {state: {order: data}})
};
In the EditOrder page I check with a UseEffect hook if a state was provided and if not the user will be redirected to a different page:
const { state } = useLocation();
const navigate = useNavigate();
useEffect(() => {
if (!state) {
navigate("some-page");
}
}, []);
The weird part is when I refresh the page I can still access it, and if I console.log(state.order) the data is still there, even when I reload with ctrl + shift + r the state stays the same, and this also happens with the empty cache and hard reload option (tried in both chrome and edge).
But when I copy the URL and past it in a new tab I immediately get redirected to "some-page"
and console.log(state) will show null.
I checked both the cookies and local storage and I can't find the state data there.
Can someone explain why is this happening and how the state data is being saved?
Edit:
Here is a youtube video that shows this behavior.
The code on the video can be found in this sandbox, when you run the code on sandbox it runs as it should, on refresh all the states reset, but when running locally this problem occurs (on 2 different computers).
A git repo about location.state
React's useLocation is based on the history library, which uses the BrowserHistory in web apps.
Some browsers, like Chrome, persist BrowserHistory state between sessions, while others (like Firefox) do not.
This is likely why you're seeing this behavior locally but not in a Sandbox. It appears that CodeSandbox's browser clears history state on refresh. It's also why, if you copy the URL into another tab, the redirect works. BrowserHistory is local to a single tab.
In short, this is intended behavior. Either you need to clear the history state manually or store your application state elsewhere (useContext could be a good choice if you want to persist across pages but not across a refresh).

Best way to dispatch an action client-side upon Sign In using Redux, React, NextAuth

I am writing a web app based on the Spotify API. Once the user logs in using NextAuth, I want the app to automatically load the user's playlists.
I currently have it set up so that there is a button to load playlists and the button does not appear unless the user is logged in - this works and is simple. However, the button is unnecessary. There is no use-case for the app that doesn't begin with loading the user's playlists.
I currently have a thunk action written which was dispatched by the "Load Playlists" button to fetch the playlists asynchronously and add the playlists to the redux state.
I can think of multiple possible options to get the automatic loading to work well, but I imagine there has to be a clean way. NextAuth has the [signIn event callback]https://next-auth.js.org/configuration/events#signin which seems like the right place to start. But since this would be run server-side, it would need some way to contact the client.
Just observe the status in. a useEffect and once the status is authenticated call the load playlist action.
import { useSession } from "next-auth/react"
export default function Component() {
const { data: session, status } = useSession()
useEffect(() => {
if (status === "authenticated") {
Load_Playlists()
}
}, [status])
return <Main>
}
what I usually do is save the Jwt on local storage then use a use effect to get it if not existing then get it from the server using the thunk action.
also, see How to wait for action to complete before redirecting in react redux? how to define the thunk

How to stop React component from re-fetching data on load when hitting browser back button

I'm using Next.js and Next Link to handle routing in my React app.
Let's say I have the 2 pages: /product-list?year=2020 and a detailed page which will be routed to /product-list/details?year=2020&month=4
In pages/product-list.js, I use React router to get the year query param to make an API call.
const ProductList = (props) => {
const router = useRouter();
const year = router.query.year;
useEffect(() => {
// Fetch API using year
}, [year]);
return (
// UI
<Link href="/product-list/details/?year=2020&month=4" />
);
}
When I navigate back from the detailed page by clicking the back button, I can see that not the whole page is rendered (verified by setting the background of the page using the Dev Console to yellow and verified it didn't change when going back).
However, it did trigger another (unnecessary) API call since the router notified my ProductList component that the year variable changed... which technically it did...
So the question is: is there any way to not trigger the year variable change notification only when coming back from another page? (think how iOS app keeps the navigation stack in memory and when you pop back the previous page isn't necessarily rendered again).
swr is the best option by vercel for better performance on data fetching and maintain state for fetched data
One way is to re-render would be to change the state variable on the submission of the Axios request causing the component to re-render automatically.

Redirect existing website link to app expo react native

I have an app that has some payment sandbox. I am using "expo-linking" Linking.openURL(sandboxURL) to open the unique payment link on a browser everytime user wants to buy the product.
If the payment is cancelled the sandbox redirects to "https://mywebsitedomain/payment/cancel"
If the payment is successful the sandbox redirects to "https://mywebsitedomain/payment/successful"
What I want to achieve is I want to the browser to redirect to my app's payment cancel and payment successful page whenever "https://mywebsitedomain/payment/cancel" and "https://mywebsitedomain/payment/successful" links get triggered in the browser.
How do I do that? I got suggestions like using deeplinking. in such case I dont necessarily need to create any link, I just need the existing website link to be redirected to my app. In that case what would be the ideal configuration?
Thank you.
In this case I would recommend using WebView instead of Linking, because Linking doesn't really give you any kind of controls to the flow after user opens an URL in the browser, DeepLinking would theoretically work, but it would open the app from the splash screen and then you would have to navigate the user manually to the screen you want him to be, I don't think this is the proper solution though..
Instead I would suggest opening an URL in Webview and injecting the custom javascript code. In this way, you would keep the user in your app and maintain the control to the flow. react-native-webview which is deprecated module and should be added through package manager has onMessage and injectedJavaScript props, and using these could solve this issue.
As an Example :
Create separate screen which contains only webview, stretched to the full screen.
Import the screen in your stacknavigator with appropriate name.
When navigating to it, pass webview props as navigation params.
Afterwards:
const jsCode = `
document.addEventListener("click", () => {
window.ReactNativeWebView.postMessage(JSON.stringify({type: "click", message : "goBack"}))
})`;
const onMsg = (event) => {
const res = JSON.parse(event.nativeEvent.data);
if (res.message === "goBack") {
navigation.goBack();
}
}
<WebView
source={{ uri: params.uri, html: params?.html }}
androidHardwareAccelerationDisabled
javaScriptEnabled
injectedJavaScript={jsCode}
javaScriptCanOpenWindowsAutomatically
collapsable
onMessage={onMsg}
/>
this is an example code which closes the webview whenever the user clicks something in there, instead you could check window.location.href, post it as a message to your app and if it equals to https://mywebsitedomain/payment/cancel do something you want to do :)
UPDATE
as mentioned in the comments, for this concrete task webview offers onNavigationStateChange prop, which is meant to determine the navigation updates in the webview. This might be a better option, as some of the websites might not allow you to inject custom javascript code. But however, javascript injection is also possible and would also be one of the solutions here.
As it's a bit hard for explaining here, I've set up an example app here, which uses both of the approaches described above:
https://github.com/RocKer004/webview-example-app
App opens react native navigation docs, if you click on React Native Express (first option) it'll take you back and close the webview (this is handled using the onNavigationStateChange prop), if you click the last option there webview is also going to be closed, but this is handled by javscript injection this time. Otherwise, you're free to browse the web.
For more info, check :
https://github.com/react-native-webview/react-native-webview

Categories