Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux-saga upload file progress event

I am using redux-saga to upload files and I am trying to figure a way to dispatch an event whenever the upload progress changes:

const data = new FormData();

data.append('file', fileWrapper.file);

const uploadedFile = yield call(request, requestURL, {
  method: 'POST',
  headers: {
     'X-Requested-With': 'XMLHttpRequest'
  },
  body: data
});

Any idea how to attach an upload progress event?

like image 836
Tomer Avatar asked Jan 17 '26 23:01

Tomer


1 Answers

First of all, the answer depends on how do you do uploadRequest.

It seems like you are using window.fetch API. This API doesn't provide you a way to receive upload progress events.

So, you need to switch to use XMLHttpRequest or a library that wraps it in a convenient way for you. I'd recommend you to look at axios and superagent. They both provide a way to listen to progress events.

The next topic is to how to dispatch progress actions in redux-saga. You need to use fork to create a forked async tasks and dispatch actions there.

function uploadEmitter(action) {
  return eventChannel(emit => {
     superagent
       .post('/api/file')
       .send(action.data)
       .on('progress', function(e) {
           emit(e);
       });
  });
}

function* progressListener(chan) {
  while (true) {
    const data = yield take(chan)
    yield put({ type: 'PROGRESS', payload: data })
  }
}

function* uploadSaga(action) {
  const emitter = uploadEmitter()
  yield fork(progressListener, emitter)
  const result = yield call(identity(promise))
  yield put({ type: 'SUCCESS', payload: result })
}

Source: https://github.com/redux-saga/redux-saga/issues/613#issuecomment-258384017

P.S. in my personal opinion, redux-saga is not an appropriate tool to implement such kind of functionality. Would be much cleaner to do this with redux-thunk:

function uploadAction(file) {
  return dispatch => {
    superagent
      .post('/api/file')
      .send(action.data)
      .on('progress', function(event) {
           dispatch({type: 'UPLOAD_PROGRESS', event});
      })
      .end(function(res) {
           if(res.ok) {
              dispatch({type: 'UPLOAD_SUCCESS', res});
           } else {
              dispatch({type: 'UPLOAD_FAILURE', res});
           }
      });
  }
}
like image 111
just-boris Avatar answered Jan 19 '26 14:01

just-boris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!