I have a React function component which dispatches an action that triggers a Saga which does two things. First, it reaches out to an API to get some data, then it sets some state based on the response. If the API call was successful, it sets two pieces of state, otherwise it sets an error.
In the component, we want to navigate to a different page only if the result of the dispatch was not setting the error, but since the error state is not available immediately after dispatch, we have to use a hacky workaround with useEffect:
export const ProductDetailsPage = () => {
const error = useSelector(selectError) as Error
// ... other useState variables here
// triggered by a button press:
const onContinue = () => {
dispatch(setPdpProductSagaAction(selectedProduct, serviceBuilderId))
// ideally we would be able to navigate here, or not, based on the error state
// set by the dispatch call
}
// hacky workaround to ensure the error state is clear
// AND we've dispatched the correct action before routing
useEffect(() => {
if (error === emptyError && deviceId) {
history.push('/nextpage')
} else {
console.log('failed to get deviceId')
}
}, [error, deviceId])
}
Here are the sagas involved in the dispatch:
export function* setPdpProductSaga() {
yield takeLeading(SET_PDP_PRODUCT, action => setPdpProduct(action, api))
}
export function* setPdpProduct(action: any, api: any): any {
yield put(setDeviceErrorAction(emptyError))
const response = yield call(
api.postDevice,
action.payload.serviceBuilderId,
action.payload.product.sku
)
if (response.error !== emptyError) {
yield put(setDeviceErrorAction(response.error))
} else {
yield put(setPdpProductAction(action.payload.product))
yield put(setDeviceIdAction(response.deviceId))
}
}
This works but... is there a better way of doing this?