ncesar
ncesar

Reputation: 1802

Proper way to handle a page refresh based on a redux request change

I have created a redux that is going to request an API and if the result is 200, I want to redirect the user to another page using history.

The problem is: I don't know how to trigger this change if the action is a success.

I could redirect the user in my useCase function but I can't use history.push pathName/state argument because it only works in a React component.

So this is what I have done in my React component:

  const acceptProposalHandler = () => {
    store.dispatch(acceptProposal(id)).then(() => {
      setTimeout(() => {
        if (isAccepted) { //isAccepted is false by default but is changed to true if the 
                          //request is 200
            history.push({
            pathname: urls.proposal,
            state: {
            starterTab: formatMessage({id: 'proposalList.tabs.negotiation'}),
             },
           });
        }
      }, 3000);
    });
  };

Sometimes it works but other times it wont. For some reason, .then is called even if the request fails.

I'm using setTimeOut because if I don't, it will just skip the if statement because the redux hasn't updated the state with isAccepted yet.

This is my useCase function from redux:

export const acceptProposal = (id: string) => async (
  dispatch: Dispatch<any>,
  getState: () => RootState,
) => {
  const {auth} = getState();
  const data = {
    proposalId: id,
  };
  dispatch(actions.acceptProposal());
  try {
    await API.put(`/propostas/change-proposal-status/`, data, {
      headers: {
        version: 'v1',
        'Content-Type': 'application/json',
      },
    });
    dispatch(actions.acceptProposalSuccess());
  } catch (error) {
    dispatch(actions.acceptProposalFailed(error));
  }
};

What I'm doing wrong? I'm using Redux with thunk but I'm not familiar with it.

Upvotes: 0

Views: 302

Answers (1)

Ross Allen
Ross Allen

Reputation: 44900

".then is called even if the request fails." <- this is because acceptProposal is catching the API error and not re-throwing it. If an async function does not throw an error, it will resolve (i.e. call the .then). It can re-throw the error so callers will see an error:

export const acceptProposal = (id: string) => async (
  // ... other code hidden
  } catch (error) {
    dispatch(actions.acceptProposalFailed(error));
    // ADD: re-throw the error so the caller can use `.catch` or `try/catch`
    throw error;
  }
};

Upvotes: 1

Related Questions