Skip to content Skip to sidebar Skip to footer

How Do I Call A Redux Saga Action In A `onclick` Event?

I just started a new project using infinitered/ignite. I've added my getUserToken function to the APITestScreen So I know that the function works as expected, but I'm not able to h

Solution 1:

Sagas are great because they allow long running processes to control application flow in a completely decoupled manner, and can be sequenced via actions, allowing you to parallelise/cancel/fork/reconcile sagas to orchestrate your application logic in a centralised place (ie think of it as being able to link together actions, incorporating side effects along the way)

By importing your generator function and calling it directly like a normal function won't work and if it did would be bypassing saga functionality, for example if you press a second time or third time on that button, it will always execute the entire generator again from start to finish, which as they involve async operations could result in you say trying to store or use a token that is then immediately invalidated by a subsequent saga

Better practice would be to have your saga always listening for specific actions to trigger further worker sagas, keeping them decoupled, and allowing them to control their own flow.

In this case you would dispatch an action onPress, and have a long running parent saga listening for that action which then hands off to your current one to do the actual work. This listening saga would then have control over cancelation of previous invocations using takeLatest would cancel the previous saga invocation, so that a subsequent button press while the previous was still in flight would always take precedence, and your token cannot accidentally go stale

// AuthActions.js

// add a new action (or more probably adapt fetchUserToken to suit)...exportconstGET_USER_TOKEN = 'auth/get-user-token'exportconstgetUserToken = (username) => ({
  type: GET_USER_TOKEN, 
  payload: username
})

// view

import {getUserToken} from'./AuthActions'// this now dispatches action (assumes username is captured elsewhere)// also assumes store.dispatch but that would more likely be done via `connect` elsewhere
<RoundedButton text="Fetch token" onPress={ () => store.dispatch(getUserToken(this.username)) }  />

// AuthSagas.js

import api from'someapi'import actions from'someactions'import {path} from'ramda'import {put, call, takeLatest} from'redux-saga/effects'importAuthActionsfrom'../Redux/AuthRedux'// this will be our long running sagaexportfunction* watchRequestUserToken() {
  // listens for the latest `GET_USER_TOKEN` action, // `takeLatest` cancels any currently executing `getUserToken` so that is always up to dateyieldtakeLatest(AuthActions.GET_USER_TOKEN, getUserToken)
}

// child generator is orchestrated by the parent saga// no need to export (unless for tests) as it should not be called by anything outside of the sagasfunction* getUserToken (action) { // the actual action is passed in as argconst username = action.payload// make the call to the apiconst response = yieldcall(api.getUser, username)

  if (response.ok) {
    const firstUser = path(['data', 'items'], response)[0]
    const avatar = firstUser.avatar_url// do data conversion here if neededyieldput(AuthActions.userSuccess(avatar))
  } else {
    yieldput(AuthActions.userFailure())
  }
}

// main.js (example taken from https://redux-saga.js.org/) adapted to suite

import { createStore, applyMiddleware } from'redux'import createSagaMiddleware from'redux-saga'import {reducer} from'./AuthRedux'import {watchRequestUserToken} from'./AuthSagas'// create the saga middlewareconst sagaMiddleware = createSagaMiddleware()
// mount it on the Storeexportconst store = createStore(
  reducer,
  applyMiddleware(sagaMiddleware)
)

// then run the saga
sagaMiddleware.run(watchRequestUserToken)

Solution 2:

On button you are calling fetchUserTocken but in script you define getUserToken.

Post a Comment for "How Do I Call A Redux Saga Action In A `onclick` Event?"