Search code examples
reactjsreduxecmascript-6material-uiredux-thunk

Disable Button When Deleting in Redux and React


I have here a problem disabling the button when deleting. Right now, it disables all the "Delete" Button of all images. I only wanted to disable the "Delete" of the currently deleting image.| So it it will prevent from deleting it again and again while it is still processing.

Codesandbox CLICK HERE

<CardActions>
    <Button
      disabled={isDeletingImages}
      variant="contained"
      size="medium"
      color="primary"
      type="button"
      onClick={() => confirmDeleteProductImage(productType?.imageFileName)}
    >
      Delete
    </Button>
  </CardActions>

Solution

  • You have a single isDeletingImages boolean state that you are using for all delete button's disabled prop.

    I suggest converting to a Map/Object of ids that are currently being deleted, and checking by id if the delete button for the currently rendered item is currently being deleted.

    1. Update the deleteProductImage action creator to dispatch the DELETE_PRODUCT_IMAGE_REQUEST and DELETE_PRODUCT_IMAGE_FAILURE action types with the current imageFileName as payload.

      export const deleteProductImage = ({
        productIndex,
        imageFileName,
        callback = () => {}
      }) => async (dispatch) => {
        try {
          dispatch({
            type: appConstants.DELETE_PRODUCT_IMAGE_REQUEST,
            payload: { productIndex, imageFileName }, // <-- pass payload
          });
      
          const response = await axios.get(
            "https://jsonplaceholder.typicode.com/todos/1"
          );
      
          if (response) {
            dispatch({
              type: appConstants.DELETE_PRODUCT_IMAGE_SUCCESS,
              payload: { productIndex, imageFileName }
            });
          }
        } catch (error) {
          dispatch({
            type: appConstants.DELETE_PRODUCT_IMAGE_FAILURE,
            payload: { productIndex, imageFileName }, // <-- pass payload
          });
        }
      };
      
    2. Update the productReducer to use an object instead of a boolean value.

      export const initialState = {
        products: [],
        errors: [],
        isDeletingImages: {} // <-- object to hold file names
      };
      
    3. Update the DELETE_PRODUCT_IMAGE_REQUEST, DELETE_PRODUCT_IMAGE_SUCCESS, and DELETE_PRODUCT_IMAGE_FAILURE reducer cases to set/clear the current delete status by the file name.

      case appConstants.DELETE_PRODUCT_IMAGE_REQUEST:
        return {
          ...state,
          isDeletingImages: {
            ...state.isDeletingImages,
            [action.payload.imageFileName]: true
          }
        };
      
      case appConstants.DELETE_PRODUCT_IMAGE_SUCCESS:
        return {
          ...state,
          isDeletingImages: {
            ...state.isDeletingImages,
            [action.payload.imageFileName]: false
          },
          products: state?.products.map((item, index) => {
            if (index !== action.payload?.productIndex) return item;
      
            return {
              ...item,
              productImages: item?.productImages.filter(
                ({ imageFileName = null }) =>
                  imageFileName !== action?.payload?.imageFileName
              )
            };
          })
        };
      
      case appConstants.DELETE_PRODUCT_IMAGE_FAILURE:
        return {
          ...state,
          isDeletingImages: {
            ...state.isDeletingImages,
            [action.payload.imageFileName]: false
          }
        };
      
    4. Update the delete button to check the isDeletingImages state with its current imageFileName value.

      <Button
        disabled={isDeletingImages[productType.imageFileName]}
        variant="contained"
        size="medium"
        color="primary"
        type="button"
        onClick={() => confirmDeleteProductImage(productType?.imageFileName)}
      >
        Delete
      </Button>
      

    Edit disable-button-when-deleting-in-redux-and-react