在 Redux 和 React 中删除时禁用按钮

Disable Button When Deleting in Redux and React

我在删除时禁用按钮时遇到问题。 现在,它禁用所有图像的所有“删除”按钮。 我只想禁用当前正在删除的图像的“删除”。| 因此它将防止在它仍在处理时一次又一次地删除它。

Codesandbox CLICK HERE

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

您有一个单一的 isDeletingImages 布尔状态,用于所有删除按钮的 disabled 属性。

我建议转换为 Map/Object 个当前正在删除的 ID,并通过 ID 检查当前呈现的项目的删除按钮是否正在被删除。

  1. 更新 deleteProductImage 动作创建者以分派 DELETE_PRODUCT_IMAGE_REQUESTDELETE_PRODUCT_IMAGE_FAILURE 动作类型,当前 imageFileNamepayload

    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. 更新 productReducer 以使用对象而不是布尔值。

    export const initialState = {
      products: [],
      errors: [],
      isDeletingImages: {} // <-- object to hold file names
    };
    
  3. 通过文件名将 DELETE_PRODUCT_IMAGE_REQUESTDELETE_PRODUCT_IMAGE_SUCCESSDELETE_PRODUCT_IMAGE_FAILURE 减速器案例更新为 set/clear 当前删除状态。

    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. 更新删除按钮以检查 isDeletingImages 状态及其当前 imageFileName 值。

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

DELETE_PRODUCT_IMAGE_REQUEST 被分派时,您可以将图像文件名作为附加负载添加到操作中(我假设文件名唯一标识要删除的内容)。

在 reducer 中,从操作负载中读取图像文件名并改变状态,以反映哪些特定图像正在被删除。例如,一个包含图像文件名作为键和 true 作为值的对象。

export const initialState = {
  products: [],
  errors: [],
  imagesInDeletion: {
    // example entry: 'nameofimage.jpg': true,
  },
};

imagesInDeletion 现在会告诉您哪个图像正在被删除。你可以根据它写一个选择器,比如isImageBeingDeleted('nameofimage.jpg'),让它return true 或者false。然后,选择器可用于按钮的 disabled 属性。

此外,reducer 还需要做一些工作才能正确更新此状态。如果图像已成功删除,则应将其从 imagesInDeletion 中删除,例如。

这是解决此问题的一种可能方法,但问题的核心是您需要为每个 product/image 跟踪图像删除生命周期的更详细状态。有时候re-modelling状态方便一点,也不失为一个好办法。