score:3

Accepted answer

TypeError: Cannot read property 'then' of undefined at

.done getter is deprecated since v1, so .toPromise() is the way to listen for a saga resolve

As for waiting sagas to complete, there is a special END action that you can dispatch to terminate saga when all its child tasks are complete, causing store.runSaga(rootSaga).toPromise() promise to resolve.

When the promise is resolved (meaning that all required data is already there), you should send result HTML received from renderToString in response. Notice that server-rendered components aren't really mounted, so componentDidMount() method won't be triggered, thus your data won't be fetched twice.

So you can modify your code as follows:

// server.js
...
import { END } from 'redux-saga';

app.get('*', (req, res) => {
    const store = createStore();
    const branch = matchRoutes(Routes, req.path);

    store.runSaga(rootSaga).toPromise().then(() => {
        res.send(renderer(req, store))
    });

    // trigger data fetching
    branch.forEach(({ route }) => {
        route.loadData && route.loadData(store)
    });

    // terminate saga
    store.dispatch(END);
});

Also, you can follow this example.

score:0

I was able to find one way to get around this problem ,But this is not that clean of a solution and i do-not want to do it for every loadData method + the saga . I was able to abstract it is there a cleaner way of achieving this as i am still not satisfied with the answer

loadData in Component

const loadData = (store) => {
    //store.dispatch({type: FETCH_USERS})
    return new Promise((resolve) => {
        store.dispatch({type: FETCH_USERS, callback: resolve })
    });
}

Saga

function asyncCallBackUtil(action){
    if (action.callback) {
        action.callback('Done');
    }
}

export function* fetchUsers(action) {
    const res = yield call(getUsers);
    yield put({ type: SAVE_USERS, payload: res.data});
    asyncCallBackUtil(action);
}

Now i can use Promise.All as mentioned on the Post

Promise.all(promises).then(data => {
    console.log('here',data);
    res.send(renderer(req, store))
})

Is there a cleaner way for this problem as i need to do it for other saga's too .


Related Query

More Query from same tag