简体   繁体   中英

This antd library component is giving me error while converting Javascript to typescript

its in the handleChange function, while setState{ imageUrl }

When I use just javascript the imagepreview is shown but shows error in typescript

https://codesandbox.io/s/react-typescript-6yn9v

import { Upload, Icon, message } from "antd";

function getBase64(img: any, callback: any) {
  const reader = new FileReader();
  reader.addEventListener("load", () => callback(reader.result));
  reader.readAsDataURL(img);
}

function beforeUpload(file: any) {
  const isJPG = file.type === "image/jpeg";
  if (!isJPG) {
    message.error("You can only upload JPG file!");
  }
  const isLt2M = file.size / 1024 / 1024 < 2;
  if (!isLt2M) {
    message.error("Image must smaller than 2MB!");
  }
  return isJPG && isLt2M;
}

function Avatar() {
  const initialState = {
    loading: false
  };

  const [state, setState] = React.useState(initialState);

  const handleChange = (info: any) => {
    if (info.file.status === "uploading") {
      setState({ ...state, loading: true });
      return;
    }
    if (info.file.status === "done") {
      // Get url from response in real world.
      getBase64(
        info.file.originFileObj,
        (imageUrl: any): any => setState({ ...state, 
            imageUrl, // shows error here but works fine in javascript
             loading: false })
      );
    }
  };

  const uploadButton = (
    <div>
      <Icon type={state.loading ? "loading" : "plus"} />
      <div className="ant-upload-text">Upload</div>
    </div>
  );
  const { imageUrl }: any = state;
  return (
    <Upload
      name="avatar"
      listType="picture-card"
      className="avatar-uploader"
      showUploadList={false}
      action="http://192.168.1.172:9595/upload/multiple"
      beforeUpload={beforeUpload}
      onChange={handleChange}
    >
      {imageUrl ? <img src={imageUrl} alt="avatar" /> : uploadButton}
    </Upload>
  );
}

This antd library component is giving me error while converting Javascript to typescript,

The problem is that React.useState infers the type of the state value it manages based on the initialState value that is passed in. So what you have:

const initialState = {
  loading: false
};
const [state, setState] = React.useState(initialState);

If you hover of state/setState in the Codesandbox, you can see that the inferred type of state is

{
  loading: boolean
}

There isn't an imageUrl field in this state type, so it's illegal to try to set that field.

There are multiple ways to tell Typescript that state can have an imageUrl field as well. One would be to explicitly annotate initialState with the desired type. Another would be to annotate the React.useState call itself.

interface AvatarState {
  loading: boolean;
  imageUrl?: string;
}
...
const initialState: AvatarState = {
  loading: false
};
const [state, setState] = React.useState(initialState);
interface AvatarState {
  loading: boolean;
  imageUrl?: string;
}
...
const initialState = {
  loading: false
};
const [state, setState] = React.useState<AvatarState>(initialState);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM