Как "yield put" в redux-saga в рамках обратного вызова?
поскольку оператор " yield "не разрешен в обратном вызове, как я могу использовать функцию" put " redux-saga в обратном вызове?
Я хотел бы иметь следующий обратный вызов:
function onDownloadFileProgress(progress) {
yield put({type: ACTIONS.S_PROGRESS, progress})
}
это не работает и заканчивается "неожиданно", потому что доходность не допускается в простой функции. В противном случае я не могу передать обратный вызов как "
3 ответов
одним из возможных решений, как вы уже упоминали, является использование channels
. Вот пример, который должен работать в вашем случае:
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)
}
}
идея здесь в том, что мы будем толкать S_PROGRESS
действие на канале для каждого события прогресса, которое испускается из RNFS.downloadFile
.
мы также должны начать другую функцию саги, которая слушает каждое нажатое действие в while
петля (watchDownloadFileChannel
). Каждый раз, когда действие было предпринято с канала, мы используем normal yield put
рассказать redux-saga
что это действие должно быть направлено.
Я надеюсь, этот ответ поможет вам.
Я попал в аналогичную ситуацию на этой неделе.
моим решением было вызвать диспетчера внутри обратного вызова и передать результат.
я обрабатывал загрузку файлов, поэтому хотел сделать 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))
}
}
}
надеюсь, что это поможет
рядом с помощью channel
как предлагает @Alex, можно также рассмотреть возможность использования call
С 'redux-saga/effects'
. The call
эффект взять функцию или Promise
.
import { call } from 'redux-saga/effects';
// ...
yield call(download.promise);