How to update navigation params after navigating to a stacked screen? - javascript

I'm using React Navigation to navigate to a stacked screen with an array (notificationStatusList) and a function (updateNotificationStatus) as params like this:
<TouchableWithoutFeedback
style={cardStyles.view}
onPress={() => navigation.navigate('EventDetails', {
event,
notificationStatusList,
updateNotificationStatus
})}
>
I receive the params in my EventDetails component like this:
const EventDetails = ({route, navigation}) => {
const { event, notificationStatusList, updateNotificationStatus } = route.params;
...
...
...
}
The updateNotificationStatus function updates the notificationStatusList. But whenever I call it I don't receive the updated notificationStatusList in my stacked screen component. I tested the function and it definitely works and updates the list.
How can I receive the updated list in my stacked screen component without having to reopen it again?

Related

React Native: Is it possible to call a function directly without any button press or TouchableOpacity?

I want to call a function on the second screen as soon as the screen navigates to the second screen. Is it possible?
This is related to firebase phone auth but here the OTP screen is on another screen not on the same screen.
on the screen, you can use useEffect to call a function on load or when a prop changes.
e.g. if you just want to load it once when page renders:
const getMyStuffFromTheApi = () => {
//TODO
}
React.useEffect(() => {
getMyStuffFromTheApi();
}, []);
e.g.2 if you want to call the function every time the prop changes
const getMyStuffFromTheApi = () => {
//TODO
}
React.useEffect(() => {
getMyStuffFromTheApi();
}, [yourProp]);

Open multiple pages with React Router Dom and Redux

I need to create a link which opens more than one route in a new tab when I click on the "Box" component. I'm using Redux
That's the template I'm following, but I'm stucked cause it seems it is not persisting state (which contains authentication datas) opening in a new tabs.
const onClickBox = () => {
onClickPageOne();
onClickPageTwo();
}
const onClickPageOne = () => {
dispatch(actions.fetchDataPageOne)
}
const onClickPageTwo = () => {
dispatch(actions.fetchDataPageTwo)
}
return (
<>
<Box
onClick = {onClickBox }
>
Click me!
</Box>
</>
)
I tried using Link component by react-router-dom but I need only one link for both pages so I don't know what to put in 'to' prop.
I tried using Redirect in onClickBox function but I don't get how to tell him to open in a new page.
You can use single function to dispatch bothh actions from there only

How to use same page anchor tags to hide/show content in Next.js

The problem
The current project is using Next.js and this situation occurred: the content needs to be hidden or replaced, matching the current category selected. I want to do it without reloading or using another route to do so. And when the user presses F5 or reloads the page the content remains unchanged.
The attempts
Next.js' showcase page apparently is able to do so. In the docs, there's a feature called 'Shallow routing', which basically gives the possibility to update the URL without realoading the page. That's what i figured out for now. Any clues on how the content is changed to match the category?
Thanks!
You can load the content on the client based on the category passed in the URL fragment (# value) using window.location.hash.
Here's a minimal example of how to achieve this.
import React, { useState, useEffect } from 'react'
const data = {
'#news': 'News Data',
'#marketing': 'Marketing Data',
default: "Default Data"
}
const ShowCasePage = () => {
const router = useRouter()
const [categoryData, setCategoryData] = useState()
const changeCategory = (category) => {
// Trigger fragment change to fetch the new data
router.push(`/#${category}`, undefined, { shallow: true });
}
useEffect(() => {
const someData = data[window.location.hash] ?? data.default // Retrieve data based on URL fragment
setCategoryData(someData);
}, [router])
return (
<>
<div>Showcase Page</div>
<button onClick={() => changeCategory('news')}>News</button>
<button onClick={() => changeCategory('marketing')}>Marketing</button>
<div>{categoryData}</div>
</>
)
}
export default ShowCasePage

What is the equivalent of viewDidAppear in React Native

Scenario:
I have a Login.js that I show as a Modal from multiple screens wherever I have placed the check to see if a user is logged in or not. After the user successfully login I change a key called LoggedIn to 1 from 0 using AsyncStorage. Now when a user successfully logged in and the Modal closes I want to rerender the scree user is on.
As I have a background in iOS, so there we have viewDidAppear that runs every time there is a Modal or user opens another app and comes back to the screen, etc.
So, what would be the equivalent of that in React Native? When a Modal close it should check if the LoggedIn value is changed in AsyncStorage and I've already prepared the components to render accordingly to the value of LoggedIn value.
Code:
I have a screen Profile.js in which I'm checking:
AsyncStorage.getItem("LoggedIn").then((value) => {
if (value === "1") {
setNeedLogin(true)
} else {
setNeedLogin(false)
}
});
const [needLogin, setNeedLogin] = useState(false);
Based on the above state I'm rendering the view as:
{
!needLogin &&
<View>
<Text>{userName}</Text>
<Text>{userEmail}</Text>
<TouchableOpacity>
<Text>Logout</Text>
</TouchableOpacity>
</View>
}
{
needLogin &&
<View>
<Text>You are not logged in</Text>
<Text>Please login or create a new account to see more information.</Text>
<TouchableOpacity onPress={() => {
alert('I am showing login screen here which is a modal')
}}>
<Text>Login or Sign Up</Text>
</TouchableOpacity>
</View>
}
Now when the Login.js renders the Modal and use logs in upon successful login I change the value of LoggedIn to 1 and close the modal which shows the Profile.js screen but when it shows it the view doesn't rerender. So, how would I check and change the state every time the profile.js view appears?
An equivalent of viewDidAppear in react native would be componentDidUpdate.
Sounds like you are dealing with 2 different components in the app, a Login and a Modal component.
One way to go about that would be passing a callback method to the Modal component if you extend the reusability of the Modal component.
For example,
class Login extends React.Component {
onLoginDone = props => {
// do some other things, like authenticate with the props data
}
render() {
<View>
<Modal onClose={this.onLoginDone} />
</View>
}
}
class Modal extends React.Component {
constructor(props) {
this.state = {
isVisible: false
}
}
onClose = () => {
this.setState({ isVisible: !this.state.isVisible })
this.props.onClose()
}
render() {this.state.isVisible && <View />}
}
Once the user has logged in (when you have validated the login credentials), you can change the state variable needLogin to false, this will re-render the screen, provided the state is connected to the screen that you want to re-render
First of all, you have to be clear in the mounting and updating process in react-native.
A componennt will re-redner whenever.
Props of the parents get updated.
State of the component gets updated.
Now coming to your problem, your login component will not re-render until the above two conditions fulfilled, and as you are using AsyncStorage it is not reactive too.
So either you have to use some reactive storage like redux-persist or you have to use focus listeners, I am assuming that you are using react-navigation so this focus listener might be a good fit for you.
Whenever the focus will be changed this function will be a trigger so you don't need to take care of updating the component etc.
import * as React from 'react';
import { View } from 'react-native';
function ProfileScreen({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// The screen is focused
// Call any action
});
// Return the function to unsubscribe from the event so it gets removed on unmount
return unsubscribe;
}, [navigation]);
return <View />;
}
https://reactnavigation.org/docs/function-after-focusing-screen/
Note: this focus listener will not work with react-native provided modal then you have to use react-navigation modal
If you don't want to use any focus listener or redux-persist you can simply check while opening the modal.
useEffect(()=>{
if(modalState){
AsyncStorage.getItem("LoggedIn").then((value) => {
if (value === "1") {
setNeedLogin(true)
} else {
setNeedLogin(false)
}
});
}
}, [modalState])

React Native FlatList jumps to the top when adding new items

I'm trying to add an Infinite Scroll feature to a FlatList:
<FlatList
data={pickupsGroups}
renderItem={({item , index}: {item: PickupGroup, index: number}) => {
return <PickingCard group={item} onPress={onPressPickup}/>
}}
onRefresh={onRefresh}
keyExtractor={item => `${item?.title}-${item?.totalSku}`}
refreshing={refreshing}
onEndReached={() => {
setPage(page + 1)
}}
onEndReachedThreshold={0.1}
/>
when the page changes, I run a GraphQL query:
const {loading} = useQuery(MY_GROUPS, {
variables: {limit: 10, page},
fetchPolicy: "network-only",
onCompleted: data => {
setPickupsGroups(pickupsGroups.concat(data.myPickupGroups.pickupGroups))
}
})
But every time I add new items to pickupGroups, the FlatList scrolls back to the top
Actually when you call method setPickupsGroups in onCompleted Method, it causes screen to re-render, try using a global variable for pickUpGroups, or if you are using apollo graphQL, then from your graphQL server try sending hasMore, and in app side call fetchMore Update Query which will not cause your screen to re-render and it won't scroll to top..

Categories

Resources