Search code examples
javascriptreactjstypescriptreact-componentreact-functional-component

Pass class state to functional component (typescript)


I have a Company.tsx component and I am using a functional component ControlledOpenSelect inside it as shown below.

How can I pass state of Company component to the functional component?

I tried using the following:

<ControlledOpenSelect dataforDownload = {this.state.selectedAsset}/>

where, selectedAsset is an object like this:

Object { id: 223, assetsTypeId: 11, fileName: "cdd_p_ABC_B43B170A4181.zip", locationTypeId: 1, path: null, fullPathName: "/mnt/nfs/Data/prod/downloader/XYZ/cdd_p_XYZ_B43B909CAC170A4181.zip", ownerId: 12354, … }

But I keep on getting following error:

Type '{ dataforDownload: []; }' is not assignable to type 'IntrinsicAttributes'.
  Property 'dataforDownload' does not exist on type 'IntrinsicAttributes'.ts(2322)

Code from Company component:

My selectedAsset is defined like this in my Company.tsx file selectedAsset: [],

export interface CompanyState extends IGridProps {

addIntendedUseVisible:boolean,
selectedAsset: []

}
 
handleCancel = (e) => {
    this.setState({  addIntendedUseVisible: false, selectedAsset: [] },   () => {
        //this.fetchRecords()
    })
}  
 
handleOk = (values) => {
    
     axios.post(`api/company/${values.id}`, {
            
        }).then((response) => {
           this.setState({
                addIntendedUseVisible: false,
                selectedAsset: []
           }
 }  

handleDownloadClick = (data, e) => {

    console.log("Date Object Test inside handleDownloadClick");
    console.log(data);

    
        this.setState({
            selectedAsset: data,
            addIntendedUseVisible: true
        })
  
  
}

public render() {

  const addDownloadDialog = this.state.addIntendedUseVisible ? (
            <Dialog visible={true} modal={true} className="add-download-popup"
                    onHide={() => this.setState({addIntendedUseVisible: false})}>
                <div style={{textAlign: 'center'}}>
                    <h5>Intended Use Dialog</h5>
                    <ControlledOpenSelect dataforDownload = {this.state.selectedAsset} handleCancel={this.handleCancel} handleOk={this.handleOk} />
                   
                </div>
            </Dialog>
        ) : null


    
    return (
            <div>
                //some other stuff
                {addDeleteDialog}

                //some other stuff
            </div>
        );
        
    

My ControlledOpenSelect functional component is as follows:

import { makeStyles, Theme, createStyles } from '@material-ui/core/styles';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles((theme) =>
  createStyles({
    button: {
      display: 'block',
      marginTop: theme.spacing(2),
    },
    formControl: {
      margin: theme.spacing(1),
      minWidth: 120,
    },
  }),
);

export default function ControlledOpenSelect() {
  const classes = useStyles();
  
  const [age, setAge] = React.useState('');
  const [open, setOpen] = React.useState(false);

 
  const handleChange = (event) => {
    setAge(event.target.value);   
  };

  const handleClose = () => {
    setOpen(false);
  };

  const handleOpen = () => {
    setOpen(true);
  };

  return (
    <div>
      <Button className={classes.button} onClick={handleOpen}>
        Open the select
      </Button>
      <FormControl className={classes.formControl}>
        <InputLabel id="demo-controlled-open-select-label">Age</InputLabel>
        <Select
          labelId="demo-controlled-open-select-label"
          id="demo-controlled-open-select"
          open={open}
          onClose={handleClose}
          onOpen={handleOpen}
          value={age}
          onChange={handleChange}
        >
          <MenuItem value="">
            <em>None</em>
          </MenuItem>
          <MenuItem value={10}>Ten</MenuItem>
          <MenuItem value={20}>Twenty</MenuItem>
          <MenuItem value={30}>Thirty</MenuItem>
        </Select>
      </FormControl>
      <Button size="small" variant="contained" color="primary" style={{marginTop: '40px'}} type="button" >OK</Button>
      <Button size="small" variant="contained" color="primary"style={{marginTop: '40px'}} type="button" onClick={handleCancel} >Cancel</Button>
    </div>
  );
}       

Solution

  • You need ControlledOpenSelect to be defined in such a way that it takes a dataforDownload prop of the type you need:

    type DataforDownload = {
      id: number;
      assetsTypeId: number;
      fileName: string;
      locationTypeId: number;
      path: null; // ?
      fullPathName: string;
      ownerId: number;
      // and whatever other properties it has
    };
    export default function ControlledOpenSelect({ dataForDownload }: { dataforDownload: DataforDownload }) {
    

    Then you can pass dataforDownload down to ControlledOpenSelect and use it inside.