Take doesn't listen for actions to be dispatched

42 Views Asked by At

I have tried to use yield take(action.type) in my saga.

function* foo() {
  console.log('pausing')
  yield take(action.type)
  console.log('passing')
}

I made sure I dispatched the right action in my useEffect


useEffect(() => {
   dispatch(action())
}, [action])

I also made sure the action is dispatched after the saga is set up correctly.

The actions are defined in Redux Toolkit's slice

import { createSlice } from '@reduxjs/toolkit';

const appSlice = createSlice({
  name: 'app',
  initialState: {},
  reducers: {
    appMounted: (state) => {
      // ... some state updates if needed
    },
    buttonClicked: (state) => {
      // ... some state updates if needed
    }
  }
});

export const { appMounted, buttonClicked } = appSlice.actions;
export default appSlice.reducer;`

Also the action type I am using in the take effect is the exact same action type I am dispatching.

The issue is that, 'pausing' got printed, but after I dispatch action, passing is not getting printed.

1

There are 1 best solutions below

0
Lin Du On

Make sure you add the redux-saga middleware to middleware when creating the redux store.

A working example:

store.ts

import { configureStore } from "@reduxjs/toolkit";
import createSagaMiddleware from "redux-saga";
import appReducer from "./app.slice";
import saga from "./saga";

let sagaMiddleware = createSagaMiddleware();

const store = configureStore({
    reducer: {
        app: appReducer,
    },
    middleware: (getDefaultMiddleware) => getDefaultMiddleware({ thunk: false }).concat(sagaMiddleware),
});

sagaMiddleware.run(saga);

export default store;

saga.ts:

import { take } from "redux-saga/effects";

export default function* foo() {
    console.log("pausing");
    yield take('app/appMounted');
    console.log("passing");
}

app.slice.ts:

import { createSlice } from "@reduxjs/toolkit";

const appSlice = createSlice({
    name: "app",
    initialState: {},
    reducers: {
        appMounted: (state) => {
            // ... some state updates if needed
        },
        buttonClicked: (state) => {
            // ... some state updates if needed
        },
    },
});

export const { appMounted, buttonClicked } = appSlice.actions;
export default appSlice.reducer;

App.tsx:

import React, { useEffect } from "react";
import "./styles.css";
import { useDispatch } from "react-redux";

import { appMounted } from "./app.slice";

export default function App() {
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(appMounted());
    }, [dispatch]);

    return (
        <div className="App">
            <h1>Hello CodeSandbox</h1>
            <h2>Start editing to see some magic happen!</h2>
        </div>
    );
}

index.tsx:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store";

const rootElement = document.getElementById("root")!;
const root = ReactDOM.createRoot(rootElement);

root.render(
    <Provider store={store}>
        <App />
    </Provider>,
);

Logs of the console:

pausing 
passing 

codesandbox