I am new at ReactJS. Still wrapping my head around all the layers with redux-store and sagas and etc. I am trying to return a simple boolean value from a saga (which at this point the saga is returning correctly) to a react component.

Here is what I have:

On the container component I have this:

export interface IKpaPickerConnectedDispatch {
    lookupListDialogToggle?: (dialogProps: ILookupListDialog) => void;
    requestSaveProfileFieldItem?: (profieFieldItem: IProfileFieldItem) => void;
    // setKpiPercentageShow?: (value: boolean) => void;
    updateKpaKpiProfilePercentage?: (toggle: boolean, jobId: number) => void;
    getKpaKpiProfilePercentageToggle?: (jobId: number) => void;
}

function mapStateToProps(state: IGlobalApplicationState, ownProps: IKpaPickerProps): IKpaPickerConnectedState {
    return {
        kpiPercentageShow: actions.requestKpaKpiToggle(state.jobProfileState.jobProfile!.id)
    };
}

On the saga side I have this:

function* requestKpaKpiToggle(action: IKpaKpiToggleReceive)
{
    try {
        const  jobId = action.payload!;
        const REQUEST_URL = `${REMPROFILE_API_URL}/KpaKpi/GetKpaKpiJobProfilePercentageToggle/${jobId}`;
        const response = yield fetch(REQUEST_URL, secureHeader('GET'));
        const json = yield response.json();
        // new method to return value and update state
        yield put(requestKpaKpiToggleReceived(json));
    }
    catch (e) {
        yield put(logError(e));
    }
}

I get the following error and don't quite understand why :-( Type 'Action' is not assignable to type 'boolean'.

Any help would be appreciated.

UPDATE

Ok after input I have manage to get 1 step closer but not there yet.

I added this in the reducer for state management

case ActionKeys.KPA_KPI_TOGGLE_RECEIVE: {
    global.console.log('KPA_KPI_TOGGLE_RECEIVE', action.payload);
    return state.set('isKpiPercentageShown', action.payload)
                .set('kpiPercentageReceived', true) as JobProfileState;
}

Problem now is it doesn't update

componentDidMount()
{
    if(this.props.getKpaKpiProfilePercentageToggle && !this.state.kpiPercentageReceived)
        this.props.getKpaKpiProfilePercentageToggle(this.props.jobId);
}

2 Answers

0
user2343647 On

You should put another action when the saga completes, an action that the relevant reducer catches, with your boolean.

You could have 2 actions:

REQUEST: handled by the saga (you already do that). REQUEST_HANDLED: dispatched by the saga, handled by a reducer.

In your saga:

yield put({type: REQEUEST_HANDLED, result: true|false});

In your reducer:

case REQUEST_HANDLED: return {...state, someFlag: someValue};

This is an example of what you could do. As I don't know exactly why you want to return a boolean and return response.json() instead.

The pattern I often use with redux-saga is have an action dispatched by a component, which is handled by a saga. When the saga is done, it dispatches an action that is handled by a reducer that changes the state in the store accordingly, telling the component the job is done.

Also, I usually have a 3rd action, which is used by the saga in the catch block, in case of an error, so the component is informed and can display a message to the user (or take any other appropriate action on error).

0
Tomer Levi On

Its seems like your error comes from the following line:

kpiPercentageShow: actions.requestKpaKpiToggle(state.jobProfileState.jobProfile!.id)

Because you have used TypeScript to identify kpiPercentageShow as a bool in the Interface of IKpaPickerConnectedDispatch.

Moreover, you are trying to get the value from your action directly which is impossible. Inspect your flow, the boolean value shouldn't come from your actions. It should be available to you in mapStateToProps after you updated your store with a reducer.