Matt
Matt

Reputation: 47

Redux Saga: How to put inside a callback

I have this code in sagas.js.

import { put, takeLatest } from "redux-saga/effects";
import { getArticles } from "../scripts/resources/articles";
import { GET_ARTICLES, SHOW_MATCHES } from "./constants";


function getMatches(action) {
    const { searchValue } = action;
    getArticles(searchValue, (matches) => {
        console.log(matches)
        put({ type: SHOW_MATCHES, payload: matches })
    })
}

export default function* rootSaga() {
    yield takeLatest(GET_MATCHES, getMatches);
}

And this is the getArticles function.

export function getArticles(input, callBack) {
    setTimeout(() => {
        callBack(filterArticles(input));
    }, 300);
};

The put inside the callback does not actually dispatch the action as I don't reach the case in the reducer. How can I dispatch this action?

Upvotes: 1

Views: 5594

Answers (1)

Benjamin
Benjamin

Reputation: 571

First, just calling put() won't pass a put effect to the channel of the saga unless preceded by yield.

Second, yield must be used inside a generator function, so you need to change the caller of yield put(...) and the caller of its caller to the generator function form, that is

function *(){
  yield anotherGeneratorFunction()
}

The following changed code just works

const { createStore, applyMiddleware } =require('redux')
const createSagaMiddleware =require('redux-saga').default
const { takeLatest ,take,put}=require('redux-saga/effects') 
const {delay} =require('redux-saga')
const sagaMiddleware = createSagaMiddleware()
const reducer=(state=[],action)=>{return [...state,action.type];}
const store = createStore(
    reducer,
    applyMiddleware(sagaMiddleware)
)

function * getMatches(action) {
    const { searchValue } = action;
    yield getArticles(searchValue, function * (matches) {
        console.log(matches)
        yield put({ type: 'SHOW_MATCHES', payload: matches })
    })
}

function * getArticles(input, callBack) {
    yield delay(300)
    yield callBack(filterArticles(input));
};

function filterArticles(input){
    return ['artical1','artical2']
}

function* rootSaga() {
    yield takeLatest('GET_MATCHES', getMatches);
}

sagaMiddleware.run(rootSaga)

store.dispatch({type:'GET_MATCHES',searchValue: 'test'})
setTimeout(() => {
    console.log(store.getState())
}, 1000);

This will output

[ 'artical1', 'artical2' ]
[ '@@redux/INIT5.m.i.0.z.9', 'GET_MATCHES', 'SHOW_MATCHES' ]

Upvotes: 2

Related Questions