Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run Logic within Logic, like you can with Sagas? #141

Open
christian314159 opened this issue Jan 31, 2019 · 2 comments
Open

Run Logic within Logic, like you can with Sagas? #141

christian314159 opened this issue Jan 31, 2019 · 2 comments

Comments

@christian314159
Copy link

Currently converting some Redux Sagas into Logics and have run into one issue:

We've got a Saga that runs another Saga within it (this Saga is also sometimes triggered independently), like so:

function* sagaA() {
  yield call(api.getSomething, a, b);
  yield sagaB();
  yield put(actionDone());
}

I'm struggling to grasp how to do this with Logic. Or could I do something where I called the other Logic's process method directly from the other?

async process({ getState }, dispatch, done) {
  await api.getSomething(a,b);
  await logicB.process({ getState}, dispatch);
  dispatch(actionDone());
  done()
}

Any ideas/help appreciated, thanks.

@Shannor
Copy link

Shannor commented Feb 13, 2019

Interesting problem. I'm not actually sure if you can do the second part you want. I have normally dispatched another process if needed since they weren't completely coupled. If the logic needs to be ran synchronously, then the only way I have seen is to put the logic there. Though I could be wrong!

@skbolton
Copy link

skbolton commented Mar 24, 2019

I would suggest a slightly different approach. We had a situation in our app where you could upload a photo, tag a photo, or upload and tag a photo. I recognized that we could have two processors that handle the tagging and uploading part and then all there was left to do was compose them together with a processor that orchestrates the work. Hopefully this code makes sense and applies to your problem. The interesting bit here is listening on the action stream for other events after this processor so you can jump back in when the thing you are delegating to is complete/errored. See the action$ below.

export const uploadAndTagPhoto = createLogic({
  type: constants.UPLOAD_AND_TAG.ACTION,
  warnTimeout: 0,
  processOptions: {
    dispatchReturn: true,
    dispatchMultiple: true
  },
  process({ action, action$ }, dispatch) {
    const { tag, projectId, file } = action.payload
    const fileNameWeAreUploading = file.name

    dispatch(Images.actions.uploadPhotoToProject(projectId, [file]))

    return action$.pipe(
      // filter stream to only photo upload events
      filter(onlyUploadEvents),
      // filter to files that have same name as one we care about
      filter(byFileName(fileNameWeAreUploading)),
      // stream could contain error event
      // in that case we want to throw and handle it as an error
      map(fileUploadAction => {
        if (
          fileUploadAction.type ===
          Project.constants.UPLOAD_AND_TAG.REJECTED
        ) {
          throw new Error()
        }

        return fileUploadAction
      }),
      // upload action can upload multiple files
      // we cannot so we grab our first file back out
      map(uploadSuccess => uploadSuccess.payload.files[0]),
      map(uploadSuccess =>
        Images.actions.tagElement(
          uploadSuccess.id,
          uploadSuccess.location,
          tag
        )
      ),
      catchError(error =>
        of({
          type: Project.constants.UPLOAD_AND_TAG.REJECTED,
          payload: {
            error,
            tag
          }
        })
      )
    )
  }
})

Also I had to adapt this example slightly because our code in our application does slightly different things but this idea is easier to explain. If I made any errors or something looks off let me know and I will fix the goof or explain better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants