2

I am new to ReactJS and have created a functional component for user input data(date and select). Another class component to invoke the APIs from the user input data. I need to pass the input values from functional component to class component.

Can you please help?

Below is the snippet for functional component with input fields. The setShowGetAPI is initially set to false and will be true once the user clicks submit button.Please let me know if the condition is correct

  const [showTable, setshowTable] = useState("hidetable");
const [showGetAPI, setShowGetAPI] = React.useState("false");  


  const [startDate, setStartDate] = useState(false);
  const [endDate, setendDate] = useState(false);
  const [expenseType, setexpenseType] = useState(false);


const showMessage = () => {
    setshowTable("");
    setShowGetAPI("true");
  };

  debugger;
  const handleEndDate = (e) => {
    setendDate(e.target.value);
  };

  const handleStartDate = (e) => {
    setStartDate(e.target.value);
  };

  const handleType = (e) => {
    console.log(e.target.value);
    setexpenseType(e.target.value);
  };
  console.log(endDate);

  return (
    <div>
      <Navbar color="info" light expand="md">
        <Nav color="info" navbar>
          <NavItem className="hdr">
            <NavLink>API Demo Tool</NavLink>
          </NavItem>
        </Nav>
      </Navbar>
      <Nav tabs>
        <NavItem>
          <NavLink
            className={{ active: activeTab === "1" }}
            onClick={() => {
              toggle("1");
            }}
          >
            Request
          </NavLink>
        </NavItem>
        <NavItem>
          <NavLink
            className={{ active: activeTab === "2" }}
            onClick={() => {
              toggle("2");
            }}
          >
            Receipt
          </NavLink>
        </NavItem>
      </Nav>
      <TabContent activeTab={activeTab}>

        <TabPane tabId="2">
          <br />
          <Form>
            <FormGroup row>
              <Label for="Start Date" sm={1}>
                Start Date
              </Label>
              <Col sm={2}>
                <Input
                  type="date"
                  name="startDate"
                  id="startDate"
                  placeholder="startDate"
                  value={startDate}
                  onChange={handleStartDate}
                />
              </Col>
            </FormGroup>
            <FormGroup row>
              <Label for="End Date" sm={1}>
                End Date
              </Label>
              <Col sm={2}>
                <Input
                  type="date"
                  name="endDate"
                  id="endDate"
                  value={endDate}
                  placeholder="endDate"
                  onChange={handleEndDate}
                />
              </Col>
            </FormGroup>
            <FormGroup row>
              <Label for="Segment" sm={1}>
                Expense Type
              </Label>
              <Col sm={2}>
                <Input
                  type="select"
                  name="expenseType"
                  value={expenseType}
                  id=" expenseType"
                  onChange={handleType}
                >
                  <option>Hotel</option>
                  <option>Airfare</option>
                  <option>Rail</option>
                  <option>All</option>
                </Input>
              </Col>
            </FormGroup>
            <FormGroup check row>
              <Col sm={{ size: 10, offset: 1 }}>
                <Button onClick={showMessage}>Submit</Button>
              </Col>
            </FormGroup>
          </Form>
          <div>

            {showGetAPI == "true" && (
            <div>
              <GetAPI
                startDt={startDate}
                endDt={endDate}
                exptype={expenseType}
              />
            </div>
          )}
          </div>
          <div class={showTable}>
            <Table></Table>
          </div>
        </TabPane>
      </TabContent>
    </div>
  );
};

export default TabsDemo;

GETAPI- This is a class component where i need the inputs values from above functional component to invoke the API with req. params

class GetAPI extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ID: [],
      ReportEntryID: [],
      token: null,
      Url: [
        {
          Url: "",
        },
      ],
    };
  }

  componentDidMount() {

    console.log(this.props.exptype);
    var accesstoken;
    let reports = [];

    axios
      .post(API, qs.stringify(requestBody), config)
      .then((result) => {
        console.log(result);
        this.setState({ token: result.data.access_token });
        accesstoken = result.data.access_token;
        console.log("access token ins " + accesstoken);
        invokeGetReport(accesstoken);
      })
      .catch((error) => {
        console.log(error);
        console.log(error.data);
      });

    function invokeGetReport(accesstoken) {
      console.log("access token is " + accesstoken);
      const config_req = {
        headers: {
          Accept: "application/json",
          Authorization: "Bearer " + accesstoken,
        },
      };

      axios
        .get(test_report_url, config_req)
        .then((resp) => {
          console.log(resp);
          console.log("data id is " + resp.data.Items.length);

          //  debugger;
          for (let i = 0; i < resp.data.Items.length; i++) {
            let reportName = resp.data.Items[i].Name;
            let reportID = resp.data.Items[i].ID;
            console.log("id is : " + reportID + "Report Name : " + reportName);
            invokeGetReportDetails(accesstoken, reportID);
            reports.push(reportID);
          }
          //  invokeGetReportDetails(accesstoken, reports);
        })
        .catch((error) => {
          console.log(error);
          console.log(error.data);
        });
    }

    function invokeGetReportDetails(accesstoken, reportID) {
      console.log("reportID in detail API is " + reportID);
      const config_req = {
        headers: {
          Accept: "application/json",
          Authorization: "Bearer " + accesstoken,
        },
      };

      axios
        .get(report_details + reportID, config_req)
        .then((resp) => {
          console.log(resp);
          console.log(
            "report data id is " + resp.data.ExpenseEntriesList.length
          );
          for (let i = 0; i < resp.data.ExpenseEntriesList.length; i++) {
            let expenseEntryId = resp.data.ExpenseEntriesList[i].ReportEntryID;
            let ExpenseTypeName =
              resp.data.ExpenseEntriesList[i].ExpenseTypeName;
            console.log(
              "id is : " +
                expenseEntryId +
                " ExpenseTypeName : " +
                ExpenseTypeName
            );
            invokeImageURL(accesstoken, expenseEntryId);
          }
        })
        .catch((error) => {
          console.log(error);
          console.log(error.data);
        });
    }

    function invokeImageURL(accesstoken, expenseEntryId) {
      console.log("expenseEntryId in detail API is " + expenseEntryId);

      const config_req = {
        headers: {
          Accept: "application/json",
          Authorization: "Bearer " + accesstoken,
        },
      };

      axios
        .get(image_url + expenseEntryId, config_req)
        .then((resp) => {
          console.log(resp);
          console.log("URL is " + resp.data.Url);
          this.setState({ Url: resp.data.Url });
        })
        .catch((error) => {
          console.log(error);
          console.log(error.data);
        });
    }

    console.log("repoddrts sdda " + reports[1]);
    console.log("prop value is " + this.props);
    // console.log("report id " + this.state.ID);
  }

  render() {
    return <h1> {this.props.startdate}</h1>;
  }
}

export default GetAPI;
ammy
  • 87
  • 1
  • 2
  • 8
  • 1
    what type of issue you'r facing ? – Arpit Vyas Jun 01 '20 at 06:00
  • when i am printing the props value it's coming as blank – ammy Jun 01 '20 at 06:35
  • What does showMessage funciton do? GetApi component is getting called on initial render, at that time all the props are set to false. Use some condition while mounting GetApi component, like use state which will be set to true on form submit. – Rohit Ambre Jun 01 '20 at 06:52
  • Rohit - showMessage function is used to call GetAPI component once the user clicks submit, the value is set to true – ammy Jun 01 '20 at 07:09

2 Answers2

2

your getApi component mount on first render of your parent component. so, you have to check using componentDidUpdate in getApi component like this.

in your getApi component

componentDidUpdate = (prevProps) => {  
  console.log('prevProps',prevProps);
  console.log('this props',this.props);
}

check if your getting props or not ? hope this will help.

Arpit Vyas
  • 2,118
  • 1
  • 7
  • 18
  • @ammy this does ans your que than please do its as marked so, can close que . – Arpit Vyas Jun 01 '20 at 06:59
  • Can you please let me know how can i prevent getAPI component from calling without submit button in above code? – ammy Jun 01 '20 at 07:06
  • `const [showGetAPI, setShowGetAPI] = useState(false); ` and update `true` in boolean from not in string like "true" and do like `{showGetAPI &&
    }`
    – Arpit Vyas Jun 01 '20 at 07:09
  • thanks, it worked.. i have a query when i am getting error at this.setState({ Url: resp.data.Url }); in GETAPI TypeError: Cannot read property 'setState' of undefined.. Please suggest.. My use-case is to store all the URLs in state and pass it to next component – ammy Jun 01 '20 at 09:30
  • done, thanks for your help, i have one last issue -i am getting error at this.setState({ Url: resp.data.Url }); in GETAPI TypeError: Cannot read property 'setState' of undefined.. Please suggest.. My use-case is to store all the URLs in state and pass it to next component – ammy Jun 01 '20 at 10:10
  • sure i'll help you. – Arpit Vyas Jun 01 '20 at 10:15
  • You can reply to my posted query- https://stackoverflow.com/questions/62130045/how-to-setstate-in-a-loop – ammy Jun 01 '20 at 10:23
  • sure i'll in sometime. – Arpit Vyas Jun 01 '20 at 10:25
0

You are passing the data from your functional component in the class component via props. So you should be able to access the data in your GetAPI class component like:

this.props.startDt
this.props.endDt
this.props.exptype

In your GetApi function, you are rendering:

render() {
    return <h1> {this.props.startdate}</h1>;
}

Instead, you are passing startDt, so you should be doing:

render() {
    return <h1> {this.props.startDt}</h1>;
}
Hashir Baig
  • 2,162
  • 15
  • 23
  • when i am printing the value it's coming as blank. I have added condition to call the GetAPI only when submit button is clicked but it's invoked without button click {showGetAPI == "true" && (
    )}
    – ammy Jun 01 '20 at 06:38
  • Can you update your code snippets in the question above? It'll make it more clear. – Hashir Baig Jun 01 '20 at 06:40
  • i have a query when i am getting error at this.setState({ Url: resp.data.Url }); TypeError: Cannot read property 'setState' of undefined.. Please suggest. My use-case is to store all the URLs in state and pass it to next component. – ammy Jun 01 '20 at 09:24
  • @ammy this error is because `this` inside the function containing ` this.setState({ Url: resp.data.Url });` is not referring to the enclosing component. Either bind `this` or use arrow function – Yousaf Jun 01 '20 at 11:18
  • @Yousaf Can you please help me with changed bind code, i am new to react – ammy Jun 01 '20 at 11:30
  • @ammy i have [answered](https://stackoverflow.com/a/62131665/6094348) your question – Yousaf Jun 01 '20 at 12:01