Reactnavigation params error "undefined is not an object evaluating route.params" - react-native

I get the error mentioned in the title and solutions like this one do not seem to work.
The user starts on screen 1 and then goes to several other screens before ending up on screen 1 again. When the user goes to screen 1 (again) I want to pass some params (and somehow use thos params to force a re-render of that component). This is my code:
Screen 1
function Screen 1(props, { route, navigation }) {
...
const { itemId } = route.params;
console.log(itemId);
Screen X (the last screen the user visits before going back to screen 1)
onPress={() => {
props.navigation.navigate("Screen_1", { itemId: Doe });
}}

You cannot mix destructuring of props and the props object at the same time, hence the statement
function Screen1(props, { route, navigation }) { ... }
is not valid.
You need to either destructure everything you need from props or use the props object.
function Screen1({ route, navigation }) {
const { itemId } = route.params
}
or
function Screen1(props) {
const { itemId } = props.route.params
}

Related

How to update the previous Screen's useState value and refresh the screen on click of goBack()

I want to update the previous screen's useState value and refresh the screen on click of goBack(), I know there is a useIsFocused() to do that but using this screen it is refreshing every time i goBack to the screen, suppose there is a ScreenA and ScreenB, So when user is performing any action in ScreeB then I am dispatching a value using redux and on goBack I am updating the useState value and refreshing the screenA, But it not working, I don't know what's the problem, Please help.
ScreenB
const leaveGroup = () => {
hideMenu();
callLikeMindsApi(`URL`, httpMethods.HTTP_PUT)
.then(response => {
if (response && response.data && response.data.success) {
hideMenu();
dispatch(updateHomeScreen(true));
props.navigation.goBack();
}
})
.catch(error => {
Alert.alert('FAILED', error.response.data.error_message);
});
};
And In ScreenA
const {updateValue} = useSelector(state => state.homeReducer);
useEffect(() => {
console.log('updateValue-1234', updateValue);
}); // it is printing true in console if (updateValue) { setOffset(1); setTotalPages(1); setMyChatRooms([]); getUserData(); } }, [isFocused]);
But
setOffset(1);
setTotalPages(1);
setMyChatRooms([]);
values are not updating, if I remove the if(updateValue){} and writing like this
useEffect(() => {
setOffset(1);
setTotalPages(1);
setMyChatRooms([]);
getUserData();
}, [isFocused]);
then code is working as expected, But it is refreshing every time I come back to the screenA and I want to refresh conditionally.
instead of props.navigation.goBack(); do
props.navigation.navigate('ScreenA',{details});
with the prop that you want pass
in screen A get that value in state from route params
ScreenA = (props) => {
const [navigateState] = useState(props.route.params.details|}{});
---while navigating to Screen B---
props.navigation.navigate('ScreenB',{details: navigateState});
...
I can't get full your code and understand the full logic but if you have already implemented redux you should use it like this:
const {updateValue} = useSelector(state => state.homeReducer);
useEffect(()=>{
if (updateValue) {
// update your screen juse by setting some states on the current component.
} else {
// don't update
}
}, [updateValue])
if you dispatch true value for updateValue whereever in your app then screen-A would be updated regardless it's getting focus or not. if you want to update screen-A only when it's on focus you should add focus condition in useEffect.

How do I set a fallback path/route with vueRouter if the navigation goBack ( < ) takes the user out of myb page?

I'm quite new with Vue, and vue-router. Right now I'm working on a page where we organize tennis matches, I have this component called goBack, it basically checks your browser history entries and take you back to the previous one, similar to the back-arrow in your browser. So I have this behavior which I don't like, and I don't know how to change it => if I set match, pass you the URL, if you enter and click on my goBack Comp it will take you out of my page. I want to avoid that with this logic, if your last browser history entry is not inside my page I want to redirect you to my home.
Here's the goBack component code:
setup(props, { attrs }) {
const router = useRouter()
const { t } = useI18n()
const goBack = (): void => {
if (attrs.onClick) return
if (router.options.history.state.back === null) {
router.replace('/')
} else {
router.back()
}
}
return {
t,
goBack
}
}
})
</script>
Thank you!

how to change params value passed to axios route to change data react native?

I am building a kind of book app (Holy Quran )... user will go for a list of Surahs, each Surah contains around 5 - 50 pages. I managed navigating user from the list to first page of each Surahs.. and through getting an api request data for first page will be shown and this is the code in the showScreen
const [quran, setQuran] = useState([]);
const page = navigation.getParam('page');
const name = navigation.getParam('name');
let pageNumber = page;
useEffect(() => {
Quran();
}, []);
const Quran = async () => {
const response = await QuranApi.get(`/${pageNumber}/quran-uthmani`);
setQuran(response.data.data.ayahs);
}
so let's imagine that first page is page number 200, I am looking for some way so when user clicks go to page 201 or 199 (next or previous) and refetching the data so show for him requested page
I need some help here please and thanks in advance
Basically you need to add some sort of button or any element in your 'markup section' which will trigger next/previous action. For example:
// The following line makes react listen for changes in page state variable.
// If you use setPage() anywhere, react will auto update all the components
// where page variable is used. You don't need to manually do it
const [page, setPage] = useState(nav.getParam('page'))
// ....
// This function does exactly that
const handleClick = event => {
if(event.target.value === 'next-page') // If next button was pressed
setPage(page + 1) // We increment the page state variable by 1
else if(event.target.value === 'prev-page') // If prev button was pressed
setPage(page - 1) // We decrement the page state variable by 1
// By doing so, react will auto update every element which uses this variable
}
// .....
// We tell react, if [page] state variable changes by user clicking
// next or previous button, fetch data from the api using updated
// page number and using that, we update the [quran] variable using
// 'setQuran()' function
useEffect(async () => {
const response = await QuranApi.get(`/${page}/quran-uthmani`)
setQuran(response.data.data.ayahs)
}, [page] );
//......
// markup section
return(
//....
<Button onClick={handleClick} value="next-page">Next Page {page + 1}</Button>
<Button onClick={handleClick} value="prev-page">Prev Page {page - 1}</Button>
//....
)
Thank you dear #Sayed it finally works but I have to make some modifications with the same idea to be
const [page, setPage] = useState(navigation.getParam('page'))
const handleRightClick = () => {
setPage(parseInt(page) + 1)
};
const handleLeftClick = () => {
setPage(parseInt(page) - 1);
}
useEffect(() => {
return () => {
console.log("cleaned up");
};
}, []);
useEffect(() => {
Quran();
}, [page]);
<Button title = 'Next Page' onPress = {handleRightClick}/>
<Button title = 'Prev-page' onPress ={handleLeftClick} />
So it's working well in that case without an error
Try this small change...
const [page,setPage]=useState(nav.getParam('page'))
useEffect(() => {
Quran();
}, [page]);
by passing an empty array as a second parameter to the useEffect function, you are telling react to only execute the side effect once (at mount time).
However if that array contains a list of state variables to watch for. React will only re-run the side effect if one of the items in this array changes.
The above mentioned change in useEffect would make your useEffect sensitive to any change in the state variable (page) passed to the useEffect array. As you pass new pagenumbers in the url as a parameter, it would result in calling useEffect everytime as the page state variable is set.
Hope this helps!

How to pass the parameter with pop in wix react-native-navigation?

how to pass parameters in pop method.
Requirement: There are two screens, screen 1 has two tabs like this: Address and Billing. There are two button on each tab layout. On click button go to screen 2 after functionality back to screen 1 but now which tab is active. If go to address tab so back to address tab same as billing tab.
Tell me how to do it?
You can pass callback while pushing screen like
Navigation.push(this.props.componentId, {
component: {
name: "Your.ScreenName",
options: {
callback:this.yourCallBackFun
}
}
});
Now while pop you can call that function like
this.props.callback();
Navigation.pop(this.props.componentId);
I think it will help you.
Screen A:
this.props.navigation.navigate('ScreenB', {func: this.func});
...
func = value => {
console.log(value);
}
Screen B:
this.props.navigation.getParam('func')();
You can call ScreenA function like this.
Screen1:
Write your navigation function and callback function in your first screen.
Pass callback function as a navigation parameter white pushing the screen.
const cbFunction = () => new Promise((resolve) => {
resolve();
});
const navigation = () => {
const { componentId } = this.props;
Navigation.push(componentId, {
component: {
name: `SCREEN_NAME`,
options: {
cbFunction: this.cbFunction
}
}
});
}
Screen2:
Write a function to go back to first screen. And call callback function from navigation parameter.
const goBack = async () => {
const { cbFunction, componentId } = this.props;
await cbFunction();
Navigation.pop(componentId);
}

Deep linking into an already open screen with different params. Is it possible?

I'm working on an app which has a category screen where the relevant posts of the category are displayed. I'm using react-navigation to navigate between the screens and handle the deep linking. The category screen can be accessed in-app or via deep link. To access the category screen via deep link I'm using something like myapp://category/:id.
If the app is already opened and is focused on the category screen the deep link does nothing.
I've currently "fixed" it using the componentDidUpdate life cycle method to compare the ID stored in the state and the ID in navigation.getParam.
componentDidUpdate = () => {
const { navigation } = this.props;
const { categoryID } = this.state;
const paramID = navigation.getParam('id', null);
if (paramID !== categoryID) {
this.setState({ categoryID: paramID }, () => {
// fetch data
});
}
}
However, this seems like a dirty fix to me. Is there a better way of doing this? Maybe opening all deep links using push instead of navigate via react-navigation?
For anyone who got here wondering how this can be done, like myself, here's the solution:
You can use the getId Stack.Screen property. You just need to return the unique ID from the getId property. Here's an example:
Let's say we have a UserScreen component, which is part of our Stack navigator. The UserScreen has one route param: userId. We can use the getId property like this:
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
const AppStack = () => {
const getUserRouteId = ({ params }) => {
return params && params.userId;
};
return (
<Stack.Navigator>
{/* Other routes */}
<Stack.Screen name="User" component={UserScreen} getId={getUserRouteId} />
</Stack.Navigator>;
);
};
Now when you try to normally navigate to this route, using the navigate function, if the param userId in the navigation action is different than on the UserScreen which you're currently on, it will navigate you to a new user screen. React Navigation deep linking uses the navigate function internally.