Ciprian Craciun - FrontEnd Developer

Ciprian Craciun

FrontEnd/Web Developer

Engineering is about making a product better, learning from past mistakes and create a process which is easy for all to understand.

Using redux-saga with Android Permissions in a react native app

Android permissions in react native app can be integrated very easily if you need something quick for a component, a list of permissions and a nice example for react-native can be found here.

But why I bring in discussion redux-saga? In my case I’m using redux-saga:
1. Login using redux-saga and store token from server to local storage (There are many debates related to storing JWT to local storage, but if anyone wants another alternative a nice article can be found here.
2. Request the necessary permissions
3. Store response of prompted permission to redux for later use

To have our permissions into redux I’ve added several functions to saga which I will explain below:

const watchLogin = function*() {
  while (true) {
    const { username, password, navigation } = yield take(types.LOGIN_REQUESTED);
    const task = yield fork(login, username, password, navigation);
    const action = yield take([types.CLIENT_UNSET, types.LOGIN_ERROR]);
    if (action.type === types.CLIENT_UNSET) yield cancel(task);
    yield call(logout);
export default watchLogin;
const login = function*(username, password, navigation) {
  let token;
  try {
    token = yield call(loginApi, username, password);
    yield put(setClient(token));
    yield put({ type: types.LOGIN_SUCCESS });
    AsyncStorage.setItem('token', JSON.stringify(token));
    yield put({ type: types.PERMISSIONS_REQUESTED });
    yield call(setPermissions);
  } catch (error) {
    yield put({ type: types.LOGIN_ERROR, error });
  } finally {
    // if canceled redirect to login
    if (yield cancelled()) {
  return token;

So the first generator function watchLogin is the root for my saga file and when my action LOGIN_REQUESTED has triggered I get the username, password, and navigation. The last parameter is used for connecting my navigation to log out functionality. The next important step for this generator is the call of login function.

I start by taking token from the API using loginApi function and then we store it to redux and local storage using setClient function and AsyncStorage.

As we can see in login function, for permissions, I’m using the action PERMISSIONS_REQUESTED and then I’m calling a new function setPermissions. Here I wanted to land with my discussion about permissions:

setPermissions is again a generator function and is looking like this:

export const setPermissions = function*() {
  try {
    const custom = yield call(requestPermission, [
    yield all( => {
        if (Object.values(item)[0] === PermissionsAndroid.RESULTS.GRANTED) {
          return put({ type: types.PERMISSIONS_SUCCESS, payload: item });
        return put({ type: types.PERMISSIONS_REJECTED, payload: item });
  } catch (err) {
    return err;
  return true;

I’m calling a new method requestPermission with an array of permissions and store the values in custom const. The requestPermission the function is looking like this:

const requestPermission = async requestedType => {
  try {
    const granted = await PermissionsAndroid.requestMultiple(requestedType);
    const access = Object.keys(granted).map(item => {
      const name = item.split('.').slice(-1)[0];
      const revObj = {};
      revObj[name] = granted[item];
      AsyncStorage.mergeItem('permissions', JSON.stringify(revObj));
      return revObj;
    return access;
  } catch (e) {
    return e;

I’m using requestMultiple() the method from react-native documentation, back to setPermission function, I have now all my values in custom const. I’m iterating through it with map and if the value is granted or deniedI’m updating my redux store.

Redux Android Requested Permissions

Because I have stored permissions into redux, I can use them easily in any react-native component. If you don’t know how to use redux check this article.

Sharing is caring!

Leave a Reply

Your email address will not be published. Required fields are marked *