I'm building a financial services app, and as a part of registration, the user is asked to provide personal information which is then sent via API to 3rd party to validate the information and provide a status on their application (approved, rejected, more info required etc.)
Fortunately, this is an SSE endpoint which allows me to listen to the status of the application and provide this status back to the user in 'real-time'. Great, no polling.
Unfortunately, however, I'm having a great deal of difficulty getting the code to look at the data stream and update state when the information I'm looking for is received.
const sse = new RNEventSource('Third party URL', {
headers: {
'Accept': 'text/event-stream',
'Authorization' : 'token'
}
});
export default function AccountRegister({ navigation, getUser, user, route}) {
const [ accountStatus, setAccountStatus ] = useState();
//This will start listening to the SSE stream, find the event that matches criteria in IF, and then update state
const startListenStatus = () => {
sse.addEventListener('message', (event) => {
const parsedData = JSON.parse(event.data);
console.log('listening..');
if (parsedData.account_id === user.accountID) {
console.log('found account');
if (parsedData.status_to === 'ACTIVE') {
updateStatus('ACTIVE');
}
}
});
}
//Stop the stream
const stopListenStatus = () => {
sse.removeAllListeners();
sse.close();
getUser();
navigation.setParams({evenListen: false});
console.log(route.params);
console.log('stopped listen');
}
//this route.params is set by the previous screen to change the accountStatus state to 'pending' once the user completes providing information for registration.
useEffect(() => {
if ((route.params && route.params.eventListen)){
updateStatus('PENDING');
} else {
getStatus();
}
console.log(route);
},[])
//This will listen to changes to accountStatus state and either start listening if the state changes to 'pending' or stop listening if the account is approved and the state is set to 'active'
useEffect(() => {
if (accountStatus === 'PENDING') {
startListenStatus();
} else if (accountStatus === 'ACTIVE') {
stopListenStatus();
}
},[accountStatus])
//just for testing...
useEffect(() => {
console.log(accountStatus);
console.log(user);
console.log('renders: ' + reerender);
})
//this makes a call to my local (node) server to update the user's account status and also changes the accountStatus state.
const updateStatus = async (status) => {
const statusReqBody = {email: user.email, accountStatus: status};
const token = await secureStoreGetValue('token');
try {
let response = await fetch(`local server`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': token,
},
body: JSON.stringify(statusReqBody)
});
let json = await response.json();
setAccountStatus(status);
console.log(json);
} catch(error) {
console.log(error);
}
}
//this gets the status of the user's Account from the local server
const getStatus = async () => {
const token = await secureStoreGetValue('token');
const { email } = user;
try {
let response = await fetch(`local server`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': token,
}
});
let json = await response.json();
setAccountStatus(json.accountStatus);
} catch(error) {
console.log(error);
}
}
return (
<>
{ accountStatus ?
<Progress
accountStatus={accountStatus}
navigation={navigation}
/>
: null }
</>
)
}
Now the the user flow is that they come to Screen 1, they are prompted to register and press a button to go to Screen 2, which will allow them to provide personal details. Once registration information is provided, they are taken back to Screen 1, and are able to see on this screen the status of their registration in 'real-time'.
All of this works fine, up until the point where the accountStatus state gets changed to pending and the listening begins. I've viewed the events being sent and the right information is being received, but the if logic is not being applied and the state is not changing.
This in particular:
if (parsedData.account_id === user.accountID) {
console.log('found account');
if (parsedData.status_to === 'ACTIVE') {
updateStatus('ACTIVE');
}
}
HOWEVER, if I hard refresh the app (expo), it will once again commence listening and will update to Active based on the event.
I'm not sure why this is required. Why would it not receive the information and rerender automatically with out refreshing?