How to “succumb” to a reduction saga in a callback?

Since the yield -statement is not allowed in the callback, how can I use the put function of the reduction saga in the callback?

I would like to have the following callback:

function onDownloadFileProgress(progress) {
  yield put({type: ACTIONS.S_PROGRESS, progress})
}

This does not work and ends with an “unexpected token”, because yield is not valid in a simple function. Otherwise, I cannot pass the callback as a " function * ", which would allow me to get a return. ES6 seems broken here.

I read that in the redux saga there are some functions called " channels ", but to be honest, I did not understand. I read several times about these channels and sample code, but in all the examples they solved very complex and different problems, not my simple case, and in the end I got up there.

Can someone tell me how to solve this problem?

The whole context:

function onDownloadFileProgress(progress) {
  yield put({type: ACTIONS.S_PROGRESS, progress})
}

export function * loadFile(id) {
  let url = `media/files/${id}`;

  const tempFilename = RNFS.CachesDirectoryPath + '/' + id;

  const download = RNFS.downloadFile( {
    fromUrl: url,          
    toFile: tempFilename,  
    background: false,
    progressDivider: 10,
    progress: onDownloadFileProgress,
  })

  yield download.promise;

}
+6
source share
3 answers

One possible solution, as you already mentioned, is to use channels. Here is an example that should work in your case:

import { channel } from 'redux-saga'
import { put, take } from 'redux-saga/effects'

const downloadFileChannel = channel()

export function* loadFile(id) {
  ...
  const download = RNFS.downloadFile({
     ...
     // push `S_PROGRESS` action into channel on each progress event
     progress: (progress) => downloadFileChannel.put({
       type: ACTIONS.S_PROGRESS,
       progress,
     }),
  })
  ...
}

export function* watchDownloadFileChannel() {
  while (true) {
    const action = yield take(downloadFileChannel)
    yield put(action)
  }
}

, , RNFS.downloadFile.

, while (watchDownloadFileChannel). , , yield put, redux-saga, .

, .

+10

.

, .

, readAsArrayBuffer(), , - :

function* uploadImageAttempt(action) {
  const reader = new FileReader();

  reader.addEventListener('loadend', (e) => {
    const loadedImage = reader.result;
    yield put(Actions.uploadImage(loadedImage)); // this errors, yield is not allowed
  });

  reader.readAsArrayBuffer(this.refs[fieldName].files[0]);
}

, readAsArrayBuffer() , :

// in my file-uploader component
handleFileUpload(e, fieldName) {
  e.preventDefault();

  const reader = new FileReader();

  reader.addEventListener('loadend', (e) => {
    const loadedImage = reader.result;
    this.props.uploadFile(
      this.constructDataObject(),
      this.refs[fieldName].files[0],
      loadedImage
    );
  });

  reader.readAsArrayBuffer(this.refs[fieldName].files[0]);

}

...

const mapDispatchToProps = (dispatch) => {
  return {
    uploadFile: (data, file, loadedImage) => {
      dispatch(Actions.uploadFile(data, file, loadedImage))
    }
  }
}

,

+1

Besides using channel@Alex as a suggestion, you can also consider using callfrom 'redux-saga/effects'. The effect calltakes on the function or Promise.

import { call } from 'redux-saga/effects';

// ...

yield call(download.promise);
Run codeHide result
0
source

Source: https://habr.com/ru/post/1016056/


All Articles