params is cached and shows older values on return to the same screen - react-native

I use react-navigation 5 and having issues because the params shows older values.
ScreenList.js
const handleFirstUser = () => {
const userDetail = {'name': 'First User'};
navigation.navigate('Details', { detail: userDetail});
}
const handleSecondUser = () => {
const userDetail = {'name': 'Second User'};
navigation.navigate('Details', { detail: userDetail});
}
The methods are called from a button and do go to Details Screen but the value is whichever was loaded initially:
ScreenDetails.js
const DetailsScreen = (props) =>{
const { navigation, route } = props;
const { params } = route;
const userDetail = params.name;
}
First time the app the loads, first user is loaded and correctly shows name. Then go back to the list screen, click user two. Still the first user is shown. I tried to clean up with useEffect but it doesnt have any effect:
useEffect(()=>{
return(()=>{
navigation.setParams({name: undefined});
});
}, [])
how can I reset setParams each it laods and use the values passed to it currently?

Related

React Native params not updating

I am trying to pass params to a detail screen for a blog post but the first time i navigate to the detail screen, the params don't get passed (shows null). then i back to original screen and click on a new blog post and it'll show params from the first blog post..
This is my function to navigate to detail screen with params:
const [blogSelected, setBlogSelected] = useState(null);
const onBlogDetail = (item) => {
setBlogSelected(item.id)
navigation.navigate( 'BlogDetail', { blog_id: blogSelected });
};
This is how i am receiving them in the detail screen:
const BlogDetailScreen = ({route}) => {
const blogID = route.params.blog_id
//Using the param in a url for an API call
const getBlogData = () => {
try{
axios.get('http://blog/'+blogID+/').then(res => {
console.log(res.data)
});
} catch (error) {
console.error(error);
}
};
}
Not sure why this is happening. Appreciate any help!! can provide more info too
try this,
const onBlogDetail = (item) => {
setBlogSelected(item.id)
navigation.navigate( 'BlogDetail', { blog_id: item.id }); // pass item.id here
};

how to handle the return values from reducer, inside a functional component

This may be a basic question, but I'm new to React Native and stuck here.
My code pasted below. reducer and functional component. I want to capture the response returned from reducer.
reducer.js
export const ActivationCenterReducer = (
state = INIT_KIT_STATE,
{ type, payload = {} }
) => {
switch (type) {
case 'KIT_ACTIVATION_SUCCESS_DATA': {
const { message, response_code, apiLoading, apiError } = payload;
return {
...state,
apiLoading: apiLoading,
apiError: apiError,
message: message,
response_code: response_code
};
}
// ...
}
// ...
};
Functional Component class:
const kitActivationCenter = ({ route, navigation }) => {
const response_code = useSelector(
store => store.kitActivationCenter.response_code
);
const handleKitActivation = () => {
/*This will call the validation() inside action.js and that follows the reducer.js file. where reducer.js file returning the values on success response. but I am not able to access that response_code returned from reducer.
How to save the response_code from the below dispatch function.*/
dispatch(Validation(locator, pin));
if (response_code === 200) {
// should navigate to the next screen
}
};
};
My question is how to capture the returned response_code from reducer.
I'm able to navigate to the next screen on clicking the submit button couple of times.I notice that first time when the dispatch function is called, the state of the response_code is not updating , hence the response_code != 200.
I want a way to capture the response and assign to variable.
Thanks in advance.
You are probably looking at the old value of response_code in your handleKitActivation.
const kitActivationCenter = ({ route, navigation }) => {
const response_code = useSelector(
store => store.kitActivationCenter.response_code
);
const handleKitActivation = () => {
dispatch(Validation(locator, pin));
// HERE the response_code does not have result value
// of your calling dispatch(Validation(locator, pin)) above yet
if (response_code === 200) {
// should navigate to the next screen
}
};
};
I suggest to move your response_code hanfling to the useEffect:
const kitActivationCenter = ({ route, navigation }) => {
const response_code = useSelector(
store => store.kitActivationCenter.response_code
);
// this effect will run whenever your response_code changes
useEffect(() => {
if (response_code === 200) {
// should navigate to the next screen
}
}, [response_code]);
const handleKitActivation = () => {
dispatch(Validation(locator, pin));
};
};

navigation.getparam latest value is not accessible inside didFocus listener

I am having 2 screens in a react native app, both the screens are functional components.
A button on screen 1 leads to screen 2, I select a few checkboxes on screen 2 and click on a button to navigate to screen 1 with adding navigation params.
coming back on screen 1 runs didFocus listener, but param values are undefined, when I hit ctrl+s on in code editor, useEffect runs and values become accessible.
After this, going back to screen 1 from screen 2 runs didfocus listener (as expected) but the param values do not update.
below is useEffect code in screen 1.
useEffect(() => {
navigation.getParam('from') == 'TagFiltersScreen' ? getAllQuestions('mostInsightful', navigation.getParam('tagsFilter')) : getAllQuestions();
const listener = navigation.addListener('didFocus', () => {
navigation.getParam('from') == 'TagFiltersScreen' ? getAllQuestions('mostInsightful', navigation.getParam('tagsFilter')) : getAllQuestions();
});
return () => {
listener.remove();
}
}, []);
I faced the same issue, and here is how I am doing it.
useEffect(() => {
const isFocused = props.navigation.isFocused();
if (isFocused) {
const { params } = props.navigation.state;
navigationFocus(params);
}
const navigationFocusListener = props.navigation.addListener('willFocus', (payload) => {
const params = payload.state.params;
navigationFocus(params);
});
return () => {
navigationFocusListener.remove();
};
}, []);
const navigationFocus = (params) => {
if (params) {
}
}
I'll be curios to know if there is a better way of doing this.

React Native hooks - correct use of useEffect()?

I'm new to hooks and ran across this setup on SO and wanted to confirm that this is the correct pattern. I was getting the RN "unmounted component" leak warning message before and this seemed to solve it. I'm trying to mimic in some way compnentDidMount. This is part of a phone number verify sign up flow and onMount I want to just check for navigation and then fire off a side effect, set mounted true and then unmount correctly.
const SMSVerifyEnterPinScreen = ({ route, navigation }) => {
const [didMount, setDidMount] = useState(false)
const { phoneNumber } = route.params
useEffect(() => {
if(navigation) {
signInWithPhoneNumber(phoneNumber)
setDidMount(true)
}
return () => setDidMount(false)
}, [])
if (!didMount) { return null }
async function signInWithPhoneNumber(phoneNumber) {
const confirmation = await auth().signInWithPhoneNumber('+1'+phoneNumber)
...
}
return (
...
)
}
RN 0.62.2 with react-nav 5 - thanks!
Since signInWithPhoneNumber is a async function and will setState you will see warning it the component is unmounted before the response is available
In order to handle such scenarios you can keep a variable to keep track whether its mounted or not and then only set state is the mounted variable is true
However you do not need to return null if component has unmounted since that doesn't accomplish anything. The component is removed from view and will anyways not render anything.
Also you do not need to maintain this value in state, instead use a ref
const SMSVerifyEnterPinScreen = ({ route, navigation }) => {
const isMounted = useRef(true)
const { phoneNumber } = route.params
useEffect(() => {
if(navigation) {
signInWithPhoneNumber(phoneNumber)
}
return () => {isMounted.current = false;}
}, [])
async function signInWithPhoneNumber(phoneNumber) {
const confirmation = await auth().signInWithPhoneNumber('+1'+phoneNumber)
...
}
return (
...
)
}

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);
}