Як отримати щось від стану / магазину всередині функції редук-саги?


122

Як отримати доступ до стану редуксації у функції саги?

Коротка відповідь:

import { select } from 'redux-saga/effects';
...
let data = yield select(stateSelectorFunction);

Відповіді:


210

Як вже говорить @markerikson, redux-sagaвідкриває дуже корисний API, select()щоб викликати selectorстан для отримання частини його частини, доступної всередині саги.

Для вашого прикладу простою реалізацією може бути:

/*
 * Selector. The query depends by the state shape
 */
export const getProject = (state) => state.project

// Saga
export function* saveProjectTask() {
  while(true) {
    yield take(SAVE_PROJECT);
    let project = yield select(getProject); // <-- get the project
    yield call(fetch, '/api/project', { body: project, method: 'PUT' });
    yield put({type: SAVE_PROJECT_SUCCESS});
  }
}

Окрім запропонованого документа @markerikson, є дуже хороший відео-посібник Д. Абрамова, який пояснює, як користуватися selectorsRedux. Перевірте також цю цікаву тему у Twitter.


3
Саме те, що я хотів .. Я не можу повірити, що я пропустив це
Адам Тал,

29

Це те, для чого призначені "селекторні" функції. Ви передаєте їм усе державне дерево, і вони повертають якийсь шматок держави. Код, який викликає селектор, не повинен знати, де в стані були дані, лише те, що вони були повернуті. Див. Http://redux.js.org/docs/recipes/ComputingDerivedData.html для деяких прикладів.

У межах саги select()API може використовуватися для виконання селектора.


Цікаво, як це було написано за 3,5 години до прийнятої відповіді, але це не було прикладом, тому не вдалося прийняти. Дякуємо все одно!
Олександр

1
@Casper - я згоден! Але справа не в тому, наскільки швидко ви тут відповідаєте на питання, а в тому, наскільки хороша ваша відповідь. Я думаю, що відповіді повинні бути простими та легкими для читання. Ця відповідь не відповідала цьому, і прийняту відповідь було набагато простіше зрозуміти.
Адам Тал

@AdamTal так, я згоден :)
Олександр

2

Я використовував eventChannel для відправки дії з зворотного виклику в межах функції генератора

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

function createEventChannel(setEmitter) {
    return eventChannel(emitter => {
        setEmitter(emitter)
        return () => {

        }
      }
    )
}

function* YourSaga(){
    let emitter;
    const internalEvents = yield call(createEventChannel, em => emitter = em)

    const scopedCallback = () => {
        emitter({type, payload})
    }

    while(true){
        const action = yield take(internalEvents)
        yield put(action)
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.