Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enable addEventListener callback to do put's

Tags:

redux-saga

I need to do a global addEventListener like thing. I am using react native and need to listen for deep link redirect events. I couldn't figure out the redux-saga way to do this. I need to enable a put from the callback within the addEventListener.

I currently do the bad hack of importing store then doing store.dispatch(...) as seen here:

import store from './flow-control'

Linking.addEventListener('url', ({ url }) => store.dispatch(_redir(url)));

Is there a redux-saga way to do this?

I was hoping to put this into a a saga maybe:

function* reduxSaga() {

    const url = yield Linking.addEventListener('url', ({ url }) => ???);

}

Or at the least replace store.dispatch with put like this:

import { put } from 'redux-saga/effects'

Linking.addEventListener('url', ({ url }) => put(_redir(url)));

Whats the right way to do this with redux-saga?

like image 700
Noitidart Avatar asked Feb 11 '18 19:02

Noitidart


People also ask

Is addEventListener a callback function?

addEventListener('click', () => { console. log('element clicked'); }); The code queries the DOM, grabs a specific element and adds a click event listener to it using addEventListener . addEventListener accepts the event type, a listener callback function and an options or useCapture parameter.

How do you call multiple functions in addEventListener?

How to invoke multiple functions on a single event listener. We can invoke multiple functions on a single event listener without overwriting each other. To do this we simply call the addEventListener() method more than once with a different function.

Why is addEventListener not working?

The "addEventListener is not a function" error occurs for multiple reasons: calling the method on an object that is not a valid DOM element. placing the JS script tag above the code that declares the DOM elements. misspelling the addEventListener method (it's case sensitive).

How do you pass parameters to a function in addEventListener?

If you like to have it within listener, you must do something like: someObj. addEventListener("click", function(){ var newVar = someVar; some_function(someVar); }, false); and use newVar instead.


1 Answers

One possible solution, is to use channels. Here is an example that should work in your case:

import { channel } from 'redux-saga'
import { put, take, race } from 'redux-saga/effects'

const redirectChannel = channel()

export function* startRedirectChannel(id) {
  Linking.addEventListener('url', ({ url }) => redirectChannel.put({
    type: REDIRECT,
    url,
  }))
}

export function* watchRedirectChannel() {
  while (true) {
    const action = yield take(redirectChannel)
    yield put(action)
  }
}

The idea here is that we will push a REDIRECT action on the channel for each url event that is emitted from Linking.addEventListener.

We also have to start another saga function that is listening to each pushed action in a while loop (watchRedirectChannel). Everytime an action has been taken from the channel, we use the normal yield put to tell redux-saga that this action should be dispatched.

Here an example using the eventChannel API:

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

export function* watchRedirect() {
  const redirectChannel = eventChannel(emitter => {
    Linking.addEventListener('url', emitter)

    // The subscriber must return an unsubscribe function
    return () => {
      Linking.removeEventListener('url', emitter)
    }
  })

  while (true) {
    const { redirectEvent, cancelEvent } = race({
      redirectEvent: take(redirectChannel),
      cancelEvent: take(ACTION_Y),
    })

    if (redirectEvent) {
      yield put({
        type: REDIRECT,
        url,
      })
    } else {
      redirectChannel.close()
      return
    }
  }
}
like image 119
Alex Avatar answered Oct 09 '22 15:10

Alex