neoslo
neoslo

Reputation: 423

Passing props from component to componet using react hooks

I have a component ProfileDetails that has a toggle function to toggle additional information on a profile. I'm importing ProfileDetails to a component ProfileTable and trying to pass isOpen with ProfileDetails. To then do a ternary operator with the condition isOpen. I am getting isOpen is undefined when doing so

ProfileDetails :

function ProfileDetails() {
    const [isOpen, setIsOpen] = useState(false);

    const toggle = () => {
        setIsOpen(!isOpen);
    };

    return (
        <>
            <Button>
                <ArrowForwardIosIcon
                    size="small"
                    onClick={toggle}></ArrowForwardIosIcon>{" "}
            </Button>
            <Slider open={isOpen} />
        </>
    );
}

ProfileTable:

import React, { useState, Fragment } from "react";
import format from "date-fns/format";
import Button from "@material-ui/core/Button";
import { withStyles } from "@material-ui/core/styles";
import DataTable from "../DataTable";
import ArrowForwardIosIcon from "@material-ui/icons/ArrowForwardIos";
import ProfileDetails from "./ProfileDetails ";




function ProfileTable(props, isOpen) {
    const { classes } = props;



    const drawerColumns = [
        {
            name: "Name",
            label: "Name",
            options: {
                filter: true,
                sort: false,
                customBodyRender: (value, tableMeta) => {
                    return (
                        <Button size="small" onClick={() => {}}>
                            {value}
                        </Button>
                    );
                }
            }
        },
        {
            name: "Address",
            label: "Address",
            options: {
                filter: false,
                sort: true
            }
        },
        {
            name: "Zip",
            label: "Zip",
            options: {
                filter: false,
                sort: true
            }
        },
        {
            name: "",
            label: "",
            options: {
                filter: false,
                sort: false,
                customBodyRender: (value, tableMeta) => {
                    return <ProfileDetails isOpen={isOpen} />;
                }
            }
        }
    ];

    const options = {

        search: false,
        print: false,
        download: false,
        selectableRows: "multiple",
        expandableRows: false
    };

    return isOpen ? (
        <DataTable
            title="Shifts to be Approved"
            data={details}
            columns={drawerColumns}
            options={options}
        />
    ) : (
        <DataTable
            title="Shifts to be Approved"
            data={details}
            columns={columns}
            options={options}
        />
    );
}

export default withStyles(styles)(ProfileTable);

Upvotes: 1

Views: 7055

Answers (3)

P. Brew
P. Brew

Reputation: 777

Thanks for updating your question. user8544110's answer is correct in terms of moving the state into the child component, else if you had more than one ProfileTable toggling one would toggle all.

ProfileTable has isOpen as undefined as functional components only have one parameter passed down for props which is an object of all the props passed to it. Therefore you can pick up the isOpen as follows:

    function ProfileTable(props) {
        const { classes, isOpen } = props;
        ...
    }

Or using arrow functions you can:

    const ProfileTable = ({ classes, isOpen }) => { 
        ...
    }

Upvotes: 5

Alberto Perez
Alberto Perez

Reputation: 2922

isOpen is undefined because your ProfileDetails component is not getting any prop in the definition of the functional component. If you want to use the component like that, you should do the following:

function ProfileDetails(isOpenProp) {
  const [isOpen, setIsOpen] = useState(isOpenProp);

  const toggle = () => {
      setIsOpen(!isOpen);
  };

  return (
      <>
        <Button>
            <ArrowForwardIosIcon
                size="small"
                onClick={toggle}></ArrowForwardIosIcon>{" "}
        </Button>
        <Slider open={isOpen} />
      </>
  );
}

That way, the initial value for isOpen would be the prop that you are passing from ProfileTable. Hope this helps.

Upvotes: 2

user8544110
user8544110

Reputation: 11

Use isOpen as a state of a component that is the parent of both ProfileDetails and ProfileTable and implement toggle function in that component too. Pass reference of the toggle function to ProfileDetails. Also, pass isOpen to ProfileTable. Now you can toggle the value of isOpen from ProfileDetails component and use that value in ProfileTable component.

Upvotes: 0

Related Questions