How to pop to the previous screen with params? - reactjs

I'm on screen A which has current state of {key:'value'} , I navigated to screen B
now I'm trying to pop from screen B to screen A again , but I don't want to lose the current state in screen A {key:'value'}
some solution is to save data in the AsynStorage , and retrive it when coming back to screen A , but that's not a good practice
.pop() do it , but what if I need to go back with additional params ?
Navigation.pop(this.props.componentId , {
passProps: {
data : 'current',
more : 'just-example'
}});
the above code , did not work
any suggestions ?
I don't use any state management tool like Redux/Mobx ..

I found a good solution is to send a callback function with the params
in screen A
getback(success)
{
alert(success);
}
Navigation.push(this.props.componentId , { component : {
name : "Payment",
passProps: {
subscription : current,
getback: this.getback
},
}});
then in screen B , when you pop to screen A fire the getback function
Navigation.pop(this.props.componentId);
this.props.getback(true);
this worked well with me

I have been working on this and I achieved with react-navigation.
Basically, your component A will send to component B the navigation state of component A. So, For B point of view it will be the prevState before stacking B component.
So when component B navigates "back" to component A using the previous navigation state it was like your navigation state never changed and now you could use the second parameter of navigate to send params back to component A.
This simple example illustrate this practice and I think it is totally valid and no AsyncStorage usage.
// In Component A use a custom prevState when goes to Component B
const { navigation } = this.props;
navigation.navigate('ComponentB', { prevState: navigation.state });
// In Component B use this custom goBack to "pop" to last screen
function goBack(data) {
const { navigation } = this.props;
const { routeName, key } = navigation.getParam('prevState');
navigation.navigate({ routeName, key, params: data });
}
// And finally in Component A again you could get data like this
function getDataFromComponentB() {
const { navigation } = this.props;
// It is null if no parameters are specified!
return navigation.state.params;
}

If the reason why you wanted navigation.pop is the animation, I have news for you: just use navigation.navigate!
When using the card presentation (for example), doing, from screen B, navigation.navigate(screenA_Id, options), works like navigation.pop

As Terrance suggested. you can use a callback in the props and fire it before pop back to the previous page
answer source: React Native Pass properties on navigator pop

I was working on similar thing which I wan't to popToTop and pass some params when I came back to top of the stack.
here how I did it in react navigation 5 :-
props.navigation.reset({ // I did reset my stack using navigation.reset() instead of using popToTop
index: 0,
routes: [
{
name: "Home", //name of screen which you wan't to come back to it
params: { isDialogOpen: true }, // params you wanna pass to the screen
},
],
});

Related

Route/Redirect to another page in new tab using useNavigate

I am using ag-grid and it has an event onSelectionChanged, which make the row clickable. When I click on row below function is called.
const onSelectionChanged = useCallback(() => {
const selectedRow = gridRef.current.api.getSelectedRows(); //get the row data
let navigate = useNavigate(); //import { useNavigate } from "react-router-dom";
navigate('/Detail', { state: { data: selectedRow[0]} }); //navigate to detail page
}, []);
The function navigates to the detail page and the state is passed. But navigate() calls the Detail page in same tab.
I want to open the page in new tab. Is this possible using this method? or there is another way to accomplish my goal?
react-router isn't supposed to help preserve state when opening things in a new tab. In fact, fundamentally, react isn't supposed to help do this.
I'd approach this in two ways:
If the data is simple enough, pass it as a query or path param using windows.open(window.open("http://link?key="+ value +"&key2="+ value2 ..."); )
Look into other state management methods like localstorage or something else

React Native Navigation Refresh List Screen on back

React Native Navigation Refresh List Screen on back:
this.props.navigation.navigate('Order List', {
order_id: this.state.order_id,
order_status: this.state.od_status,
})
What you want to achive isn't clear, but if want to modify your list of data when going back to your previous screen you could simply use useEffect and modify your list in there.
Note: Your list has to be stored in a local state otherwise the screen wouldn't re-render when updating the list and youl would see no changes on your screen.
better description of the problem would be helpful, but this is general solution for class based components:
componentDidMount() {
this._unsubscribe = this.props.navigation.addListener('focus', () => {
this.loadDataFunction();
}
}
componentWillUnmount() {
this._unsubscribe();
}

Preserve internal state on page refresh in React.js

It must be pretty regular issue.
I'm passing props down to the children and I'm using it there to request to the endpoint. More detailed: I'm clicking on the list item, I'm checking which item was clicked, I'm passing it to the child component and there basing on prop I passed I'd like to request certain data. All works fine and I'm getting what I need, but only for the first time, ie. when refreshing page incoming props are gone and I cannot construct proper URL where as a query I'd like to use the prop value. Is there a way to preserve the prop so when the page will be refresh it will preserve last prop.
Thank you!
(You might want to take a look at: https://github.com/rt2zz/redux-persist, it is one of my favorites)
Just like a normal web application if the user reloads the page you're going to have your code reloaded. The solution is you need to store the critical data somewhere other than the React state if you want it to survive.
Here's a "template" in pseudo code. I just used a "LocalStorage" class that doesn't exist. You could pick whatever method you wanted.
class Persist extends React.Component {
constuctor(props) {
this.state = {
criticalData = null
}
}
componentDidMount() {
//pseudo code
let criticalData = LocalStorage.get('criticalData')
this.setState({
criticalData: criticalData
})
}
_handleCriticalUpdate(update) {
const merge = {
...LocalStorage.get('criticalData')
...update
}
LocalStorage.put('criticalData', merge)
this.setState({
criticalData: merge
})
}
render() {
<div>
...
<button
onClick={e => {
let update = ...my business logic
this._handleCriticalUpdate(update) //instead of set state
}}
>
....
</div>
}
}
By offloading your critical data to a cookie or the local storage you are injecting persistence into the lifecycle of the component. This means when a user refreshes the page you keep your state.
I hope that helps!

How to made some function of component A running when close component B

I try to used react-navigation!
My app have two Component : A and B
From A i go component B, inside B i do some function and got value like isreload type boolean, i want to go back A and put it to A! Inside A if receiver value isreload, i do some function! Anyone can suggest me solution for handle this! Thanks guys so much!
here is my code at Component B, i don't know how to receiver reload at Component A and check if reload true: re-render component A, fail: stay
navigateToNewsFeed = (routeName, _reload) => {
const backActionWithParams = NavigationActions.back({
index: 0,
actions: [NavigationActions.navigate({
routeName,
params: { isreload: _reload }
})]
});
this.props.navigation.dispatch(backActionWithParams);
}
This question is related to event system in react native.
I suggest you refer to DeviceEventEmitter
You could send message by DeviceEventEmitter.emit('shouldUpdate', reRender); in Component B , and register listener in Component A by
DeviceEventEmitter.addListener('shouldUpdate', (reRender) => {
if(reRender){
this.setState(...)
} else {
// stay
}
});
Remember to import DeviceEventEmitter

React Router "Link to" does not load new data when called from inside the same component

Background
I am building an app with the following details
react
react-router
redux
it is universal javascript
node js
Problem
When routing with the Link tag from component to component it works perfectly. It calls the data that the component requires and renders the page. But when I click on a Link that uses the same component as the current one all I see is the url change.
Attempts
Things I have tried to get this to work.
Attempt 1
So far I have tried the steps in this question but the solution wont work for me. This was the code I implemented
componentWillReceiveProps(nextProps) {
if (nextProps.article.get('id') !== this.props.article.get('id')) {
console.log('i got trigggerd YESSSSSSSSSSSSSSS');
}
}
But the variable nextProps is always the same as the current props.
Attempt 2
I decided to call the same code I use in componentWillMount but that didn't work either.
componentWillMount() {
let { category, slug } = this.props.params;
this.props.loadArticleState({ category, slug });
}
It just creates an infinite loop when I put this into componentWillReceiveProps.
Conclusion
I belief the problem is clicking the link never calls the data associated with it. Since the data is loaded with
static fetchData({ store, params }) {
let { category, slug } = params;
return store.dispatch(loadArticleState({ category, slug }));
}
Any help is appreciated.
Solution I Used
I created a function to test if the previous data is the same as the changed data.
compareParams(prevProps, props) {
if (!prevProps || typeof prevProps.params !== typeof props.params) {
return false;
}
return Object.is(props.params, prevProps.params);
}
So this tests
are there any previous props?
and then if the props are equal to the previous props?
then return false if there are if this is the case
if not then we see compare props and previous props parameters
In ComponentDidUpdate
In the compoonentDidUpdate we use this function to determine if the data should be updated
componentDidUpdate(prevProps) {
if (this.compareParams(prevProps, this.props)) {
return;
}
this.props[this.constructor.reducerName](this.props.params);
}
Conclusion
This code updates the body of a page that uses the same react component if it receives new data.
maybe you can try use onChange event on Route component, check Route API and then signal to child component that refresh is needed...

Resources