nmnsharma007
nmnsharma007

Reputation: 236

How to pass argument to componentDidMount method in React JS

I want to take input from the user through a button in App.js, fetch some information(the data id) from the site API and then use the fetched information(the id) to display the desired info to user by sending the id to Population.js but it just isn't working correctly. I am thinking that probably the componentDidUpdate needs some argument because the fetch request that I have to send needs user input to work.Also, I think that my code is fetching information even before user presses the button because the console isn't displaying the correct id that I need(it displays 4-5 values and all are not correct). It works fine if I hardcode the values though.Basically, I want to take input through button, use that input to fetch something, then use the fetched thing to fetch something else and then display the fetched info.Please help me. I am a beginner at React. Here is the APP.js


import React from 'react';
import './App.css';
import Population from './Population.js';

class App extends React.Component {

    constructor(props) {
        super(props);
        this.state = { name: "" ,info : {},formSubmit: false};
        this.handleInput = this.handleInput.bind(this);
        this.handleFormSubmit = this.handleFormSubmit.bind(this);
    }   
    
      handleInput (event) {
        console.log(event.target.value);
      }
    
      handleFormSubmit (event) {
        event.preventDefault();
        console.log("the value " + event.target.value);
        this.setState({formSubmit: true,name : event.target.value});
      }
      
        componentDidMount(){//the value property needs to be fetched from user 
        fetch(`https://wft-geo-db.p.rapidapi.com/v1/geo/cities?namePrefix=${value}`, {
            "method": "GET",
            "headers": {
                "x-rapidapi-key": "c4ab967692mshc65dd5c6e10a987p1790bejsn81ea7b831444",
                "x-rapidapi-host": "wft-geo-db.p.rapidapi.com"
            }
        })
        .then(response => response.json())
        .then(data => {
            const newInfo = data.data;
            const newName = newInfo[0].wikiDataId;
            const newState = Object.assign({},this.state,{
                info : newInfo,
                name : newName
            });
            this.setState(newState);
            console.log("The sent code " + this.state.name);
        })
        .catch(err => {
            console.error(err);
        });
      }

      render () {

        return (
          <div className="App">
            <h1>
                Enter the name of the city: <br/>
            </h1>
            <form >
              <label>
                Enter the city name to get the population:{" "}
                <input
                  type="text"
                />
                <button onClick = {this.handleFormSubmit}>Enter</button>  
                  
              </label>
              
            </form>
            {this.state.formSubmit && <Population name={this.state.name} />}
          </div>
        );

      }
}

export default App;

and here is the Population.js

import React from 'react';
import "./App.css";
class Population extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            info : {},
            population : 0,
        }
        this.getPopulation = this.getPopulation.bind(this);
    }

    getPopulation(name){
        fetch(`https://wft-geo-db.p.rapidapi.com/v1/geo/cities/${name}`, {
        "method": "GET",
        "headers": {
           "x-rapidapi-key": "c4ab967692mshc65dd5c6e10a987p1790bejsn81ea7b831444",
           "x-rapidapi-host": "wft-geo-db.p.rapidapi.com"
            }   
        })
       .then(response => response.json())
       .then((data) => {
           const newInfo = data.data;
           const newPopulation = newInfo.population;
           const newState = Object.assign({},this.state,{
               info : newInfo,
               population : newPopulation
           });
           this.setState(newState);
           console.log(this.state.info);
       })
       .catch(error => {
            console.error(error);
        });
    
    }

    componentDidMount(){
        this.getPopulation(this.props.name);
        console.log("The name " + this.props.name);

    }

   render(){
    return (
        <div className="App">
            The population is {this.state.population}
        </div>
        );
    }

}
export default Population;

Upvotes: 1

Views: 1883

Answers (2)

Guruparan Giritharan
Guruparan Giritharan

Reputation: 16334

Your requirement is different and you dont have to use componentDidMount here as you are going to do the service call after the user presses the search button.

I have modified your code to work on button press and it passes a code to the population component which does a call to api on both componentDidMount and componentDidUpdate as the code may be update in future

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { name: "", info: {}, formSubmit: false, code: "" };
    this.handleInput = this.handleInput.bind(this);
    this.handleFormSubmit = this.handleFormSubmit.bind(this);
  }

  handleInput(event) {
    console.log(event.target.value);
     this.setState({ name: event.target.value, formSubmit: false });
  }

  handleFormSubmit(event) {
    event.preventDefault();

    fetch(
      `https://wft-geo-db.p.rapidapi.com/v1/geo/cities?namePrefix=${this.state.name}`,
      {
        method: "GET",
        headers: {
          "x-rapidapi-key":
            "",
          "x-rapidapi-host": "wft-geo-db.p.rapidapi.com"
        }
      }
    )
      .then((response) => response.json())
      .then((data) => {
        const newInfo = data.data;
        const newName = newInfo[0].wikiDataId;
        const newState = Object.assign({}, this.state, {
          info: newInfo[0],
          code: newName,
          formSubmit: true
        });
        this.setState(newState);
        console.log("The sent code " + this.state.name);
      })
      .catch((err) => {
        console.error(err);
      });
  }

  componentDidUpdate() {
    //the value property needs to be fetched from user
  }

  render() {
    return (
      <div className="App">
        <h1>
          Enter the name of the city: <br />
        </h1>
        <form>
          <label>
            Enter the city name to get the population:{" "}
            <input
              type="text"
              value={this.state.name}
              onChange={this.handleInput}
            />
            <button onClick={this.handleFormSubmit}>Enter</button>
          </label>
        </form>
        {this.state.formSubmit && <Population name={this.state.code} />}
      </div>
    );
  }
}

And the population component would be like

class Population extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      info: {},
      population: 0
    };
    this.getPopulation = this.getPopulation.bind(this);
  }

  getPopulation(name) {
    fetch(`https://wft-geo-db.p.rapidapi.com/v1/geo/cities/${name}`, {
      method: "GET",
      headers: {
        "x-rapidapi-key": "",
        "x-rapidapi-host": "wft-geo-db.p.rapidapi.com"
      }
    })
      .then((response) => response.json())
      .then((data) => {
        const newInfo = data.data;
        const newPopulation = newInfo.population;
        const newState = Object.assign({}, this.state, {
          info: newInfo,
          population: newPopulation
        });
        this.setState(newState);
        console.log(this.state.info);
      })
      .catch((error) => {
        console.error(error);
      });
  }

  componentDidMount() {
    if (this.props.name) {
      this.getPopulation(this.props.name);
      console.log("The name " + this.props.name);
    }
  }

  componentDidUpdate() {
    if (this.props.name) {
      this.getPopulation(this.props.name);
      console.log("The name " + this.props.name);
    }
  }

  render() {
    return <div className="App">The population is {this.state.population}</div>;
  }
}

Upvotes: 1

Shree Charan
Shree Charan

Reputation: 573

The componentDidMount function is called as soon as the component mounts and hence it is performing the fetch operation as soon as the component mounts. If you want the fetch operation to occur on a button click you will have to place the code inside a custom function and call it on button click. I don't think you can pass any props to component did mount as you cannot control when it is called. The componentDidUpdate might be of use to you componentDidUpdate

Upvotes: 0

Related Questions