skip to Main Content

I am using the Upload component antd. For any reason it shows the upload file in red even though when submit image successfully change. I try returning false from beforeUpload but if I do this while using antd-img-crop, the cropping functionality does not work. How to remove color red when upload the file while keep ant-img-crop function?
How to make border not turn red when upload picture?

i try different picture but not all error but all picture success change when submit

here the code

const Setting = () => {
  const [memberData, setMemberData] = useState<MemberDataProps>();
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [phoneNumber, setPhoneNumber] = useState('');
  const [expiredDate, setExpiredDate] = useState('');
  const [isPhoneInvalid, setIsPhoneInvalid] = useState(false);
  const [isSubscribe, setIsSubscribe] = useState(false);
  const [newPicture, setNewPicture] = useState<any[]>([]);


  const handleImageUpload = async (info: any) => {
    let fileList = [...info.fileList];
    fileList = fileList.slice(-1);

    fileList = fileList.map((file) => {
      if (file.response) {
        file.url = file.response.url;
      }
      return file;
    });

    setNewPicture(fileList);
  };

  const onPreview = async (file: UploadFile) => {
    let src = file.url as string;
    if (!src) {
      src = await new Promise((resolve) => {
        const reader = new FileReader();
        reader.readAsDataURL(file.originFileObj as RcFile);
        reader.onload = () => resolve(reader.result as string);
      });
    }
    const image = new (Image as any)();
    image.src = src;
    const imgWindow = window.open(src);
    imgWindow?.document.write(image.outerHTML);
  };


  console.log(newPicture);
  const toast = useToast();

  const navigate = useNavigate();

  const handlePhoneNumber = (value: string) => {
    const isNumber = value.match(/^[0-9b]+$/);

    setPhoneNumber(value);

    if (isNumber) {
      setIsPhoneInvalid(false);
    } else {
      setIsPhoneInvalid(true);
    }

    if (value.length < 11) {
      setIsPhoneInvalid(true);
    }
  };

  const handleSubmit = async () => {
    const formData = new FormData();

    formData.append('name', name);
    formData.append('phoneNumber', phoneNumber);
    if (newPicture) {
      formData.append('profilePhoto', newPicture[0]?.originFileObj || newPicture[0]?.url);
    }
    formData.append('subscribeNewsletter', String(isSubscribe));

    try {
      await fetchFormData({
        method: 'PATCH',
        path: 'member/data',
        data: formData,
      }).then((response) => {
        if (!response.error) {
          toast({
            title: 'Berhasil',
            description: 'Profil Anda telah berhasil diperbaharui',
            status: 'success',
            duration: 9000,
            isClosable: true,
          });
          getMemberData();
        } else {
          toast({
            title: 'Error',
            description: response.message,
            status: 'error',
            duration: 9000,
            isClosable: true,
          });
        }
      });
    } catch (error) {
      toast({
        title: 'Error',
        description: error.message,
        status: 'error',
        duration: 9000,
        isClosable: true,
      });
    }
  };

  const getMemberData = async () => {
    try {
      await fetchRequest({ method: 'GET', path: 'member' }).then((response) => {
        if (!response.error) {
          setMemberData(response);
          setPhoneNumber(response.phoneNumber);
          setExpiredDate(
            dayjs(response.membershipValidEnd).format('DD MMMM YYYY')
          );
          setEmail(response.email);
          setName(response.name);
          setIsSubscribe(response.subscribeNewsletter);
        }
      });
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    getMemberData();
  }, []);

  return (
    <Box>
      <Box h="30px" paddingLeft={{ base: '10px', lg: '3%' }} w="100%">
        <CustomBreadcrumb breadcrumbs={BREADCRUMB_PENGATURAN} />
      </Box>
      <Stack
        w={{ xl: '100%' }}
        direction={['column', 'row']}
        spacing={{ md: '50px', base: '30px' }}
        paddingLeft={{ base: '3%' }}
        paddingRight={{ base: '3%' }}
        paddingTop={{ base: '0px', lg: '20px' }}
      >
        <Box
          w={{ md: '20%' }}
          h="400px"
          display={{ md: 'inline', base: 'none' }}
        />
        <Box w="100%">
          <VStack w="100%" marginBottom="10px">
         

<ImgCrop cropShape="round">
      <Upload
        action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
        name="Profile Picture"
        listType="picture-circle"
        fileList={newPicture}
        onChange={handleImageUpload}
        onPreview={onPreview}
        // beforeUpload={()=> false}
        showUploadList={{
          showPreviewIcon:false
        }}
       
      >
        {newPicture.length < 1 && '+ Edit'}
      </Upload>
      
    </ImgCrop>
 
          </VStack>
          <VStack align="start">
            <Text className="fontSemiBold" fontSize={{ lg: 'md', base: 'sm' }}>
              Name
            </Text>
            <InputGroup paddingTop="5px" zIndex={0}>
              <InputLeftElement
                pointerEvents="none"
                children={<Image src={imgUsernameIcon} w="30%" />}
                paddingTop="5px"
              />
              <Input
                type="text"
                placeholder="Masukkan Nama"
                _focus={{ boxShadow: 'none', borderColor: RED }}
                fontSize={{ lg: 'md', base: 'sm' }}
                value={name}
                onChange={(e: any) => setName(e.target.value)}
                errorBorderColor={RED}
                isInvalid={name === ''}
              />
            </InputGroup>
            <Text className="fontSemiBold" fontSize={{ lg: 'md', base: 'sm' }}>
              Email
            </Text>
            <InputGroup paddingTop="5px" zIndex={0}>
              <InputLeftElement
                pointerEvents="none"
                children={<EmailIcon color="#AAAAAA" />}
                paddingTop="5px"
              />
              <Input
                type="email"
                placeholder="Masukkan Email"
                _focus={{ boxShadow: 'none', borderColor: RED }}
                fontSize={{ lg: 'md', base: 'sm' }}
                value={email}
                disabled
              />
            </InputGroup>
            <Checkbox
              isChecked={isSubscribe}
              onChange={(e: any) => setIsSubscribe(e.target.checked)}
              colorScheme="red"
            >
              Kirimkan saya berita rutin dari Astagatra Institute
            </Checkbox>
            <Text className="fontSemiBold" fontSize={{ lg: 'md', base: 'sm' }}>
              Nomor Telepon
            </Text>
            <InputGroup paddingTop="5px" zIndex={0}>
              <InputLeftElement
                pointerEvents="none"
                children={<PhoneIcon color="#AAAAAA" />}
                paddingTop="5px"
              />
              <Input
                type="text"
                placeholder="Masukkan Nomor HP"
                _focus={{ boxShadow: 'none', borderColor: RED }}
                fontSize={{ lg: 'md', base: 'sm' }}
                value={phoneNumber}
                onChange={(e: any) => handlePhoneNumber(e.target.value)}
                isInvalid={isPhoneInvalid}
                errorBorderColor={RED}
              />
            </InputGroup>
            <Text className="fontSemiBold" fontSize={{ lg: 'md', base: 'sm' }}>
              Masa Berlaku Keanggotaan
            </Text>
            <InputGroup paddingTop="5px" zIndex={0}>
              <InputLeftElement
                pointerEvents="none"
                children={<CalendarIcon color="#AAAAAA" />}
                paddingTop="5px"
              />
              <Input
                type="text"
                placeholder="Masa Berlaku Keanggotaan"
                _focus={{ boxShadow: 'none', borderColor: RED }}
                fontSize={{ lg: 'md', base: 'sm' }}
                value={expiredDate}
                disabled
              />
            </InputGroup>
            <Text className="fontSemiBold" fontSize={{ lg: 'md', base: 'sm' }}>
              Password
            </Text>
            <Button
              rightIcon={<ChevronRightIcon color={GREY} />}
              w="100%"
              bg={LIGHTGREY}
              color={GREY}
              _focus={{ boxShadow: 'none' }}
              justifyContent="space-between"
              onClick={() => navigate(MEMBER_SETTING_RESET_PASSWORD)}
            >
              <Text>Ubah Password</Text>
            </Button>
            <Box textAlign="end" w="100%">
              <CustomButton
                text="SIMPAN"
                variant="red"
                icon="none"
                w="150px"
                onClick={handleSubmit}
              />
            </Box>
          </VStack>
        </Box>
        <Box
          w={{ md: '20%' }}
          h="400px"
          display={{ md: 'inline', base: 'none' }}
        />
      </Stack>
    </Box>
  );
};

export default Setting;

2

Answers


  1. You should repelace action prop from Upload component to your backend upload route instead of pointing to mocky.io so antd will auto upload your images to this url.

    You can find examples in antd docs here

    Login or Signup to reply.
  2. First "beforeUpload" prop is to "Hook function which will be executed before uploading. Uploading will be stopped with false or a rejected Promise returned. When returned value is Upload.LIST_IGNORE, the list of files that have been uploaded will ignore it." according to ant design documentation.

    Seems like you want to use ant design file upload as form field.
    you can use "customRequest" property to fix your problem. demo

    import React, { useState } from "react";
    import "./index.css";
    import { PlusOutlined } from "@ant-design/icons";
    import { Button, Modal, Upload } from "antd";
    import type { RcFile, UploadProps } from "antd/es/upload";
    import type { UploadFile } from "antd/es/upload/interface";
    
    const getBase64 = (file: RcFile): Promise<string> =>
      new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result as string);
        reader.onerror = (error) => reject(error);
      });
    
    const App: React.FC = () => {
      const [previewOpen, setPreviewOpen] = useState(false);
      const [previewImage, setPreviewImage] = useState("");
      const [previewTitle, setPreviewTitle] = useState("");
      const [fileList, setFileList] = useState<UploadFile[]>([
        {
          uid: "-1",
          name: "image.png",
          status: "done",
          url: "https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png",
        },
      ]);
    
      const handleCancel = () => setPreviewOpen(false);
    
      const handlePreview = async (file: UploadFile) => {
        if (!file.url && !file.preview) {
          file.preview = await getBase64(file.originFileObj as RcFile);
        }
    
        setPreviewImage(file.url || (file.preview as string));
        setPreviewOpen(true);
        setPreviewTitle(
          file.name || file.url!.substring(file.url!.lastIndexOf("/") + 1)
        );
      };
    
      const handleChange: UploadProps["onChange"] = ({ fileList: newFileList }) =>
        setFileList(newFileList);
    
      const uploadButton = (
        <div>
          <PlusOutlined />
          <div style={{ marginTop: 8 }}>Upload</div>
        </div>
      );
      return (
        <>
          <Upload
            listType="picture-circle"
            fileList={fileList}
            onPreview={handlePreview}
            onChange={handleChange}
            customRequest={({ onSuccess, file }) => {
              onSuccess("ok");
            }}
          >
            {fileList.length == 1 ? null : uploadButton}
          </Upload>
          <Modal
            open={previewOpen}
            title={previewTitle}
            footer={null}
            onCancel={handleCancel}
          >
            <img alt="example" style={{ width: "100%" }} src={previewImage} />
          </Modal>
          <Button
            onClick={() => {
              console.log(fileList);
            }}
          >
            Submit
          </Button>
        </>
      );
    };
    
    export default App;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search