0

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?

Matt
  • 37
  • 2
  • 6
  • A couple tips to start down the right track: an action dispatch is handled totally independent of a saga though, so using that as a base-case to test is where to start. Also there's no action or action dispatch in the code in the post yet. Redux-saga is awesome, but I'd focus on getting a redux action to work through to the reducer first. your root saga yield probably should be a yield* so that it always executes "takeLatest". You probably want ```function* getMatches``` so that getMatches is a generator function so that the effects from redux-saga work. – The Brofessor Jun 21 '18 at 04:07
  • `{ type: SHOW_MATCHES, payload: matches }` This is not an action? – Matt Jun 21 '18 at 04:27
  • that is an action, but there are a lot of typos in the way of getting that action to fire. I was recommending starting with a base-test-case of making sure your code can dispatch an action through redux normally, without redux-saga. From there you can start understanding / removing all the typos. For example you need ```getMatches``` to be a generator function to yield a ```put``` effect. you also need to explicitly tell the generator to ```yield``` the effect, rather than just calling ```put```. I.e. ```yield put({ type: "EXAMPLE", payload: data});``` – The Brofessor Jun 21 '18 at 04:37
  • In this case I cannot call `yield` with the `put` because I am passing it to `getArticles` which is not a generator so it throws an error. My next thought is to pass the `dispatch` function into the saga but I'm not sure how to do that. – Matt Jun 21 '18 at 04:45
  • If you want your saga to fire after some delay use throttle from saga/effects – user93 Jun 21 '18 at 06:42
  • Possible duplicate of [How to "yield put" in redux-saga within a callback?](https://stackoverflow.com/questions/43031832/how-to-yield-put-in-redux-saga-within-a-callback) – Alex Jun 21 '18 at 11:25

1 Answers1

2

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' ]
Benjamin
  • 371
  • 1
  • 4
  • 11