J.Edge
J.Edge

Reputation: 49

Passing the state of a Child component to a Parent?

I think I know what I need to do to make my searchLocationChange function work, but I'm not sure quite how to do it. Please forgive the indentation, was grappling a fair bit with StackOverflow's WYSIWYG!

Here's my Parent component setup:

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            forecasts: [],
            location: {
                city: '',
                country: '',
            },
            selectedDate: 0,
            searchText: '',
        };
        this.handleForecastSelect = this.handleForecastSelect.bind(this);
        this.searchLocationChange = this.searchLocationChange.bind(this);
    }
}

With this specific function I want to make work:

searchLocationChange() {
    console.log(this.state.searchText);
    Axios.get('https://mcr-codes-weather.herokuapp.com/forecast', {
            params: {
                city: this.state.searchText,
            },
        })
        .then((response) => {
            this.setState({
                forecasts: response.data.forecasts,
                location: {
                    city: response.data.location.city,
                    country: response.data.location.country,
                }
            });
        });
}

And in my Child component, the logic is:

class SearchForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            searchText: '',
        };
        this.handleInputChange = this.handleInputChange.bind(this);
    }

    handleInputChange(event) {
        const enteredText = event.target.value;
        this.setState({
            searchText: enteredText
        });
    }

    render() {
        return (
            <span className="search-form">
              <div className="search-form__input"><input type="text" value={this.state.searchText} onChange={this.handleInputChange} /></div>
              <div className="search-form__submit"><button onClick={this.props.searchLocationChange}>Search</button></div>
            </span>
        );
    }
}

I realise I'm trying to update the Parent component with searchText from the state of the Child component, but I can't figure out what I need to change to make this work. I have a sneaking suspicion I'm 99% of the way there, and it's only a few more lines I need, but I could be way off?

Upvotes: 1

Views: 58

Answers (3)

Ankush Sharma
Ankush Sharma

Reputation: 677

You should call the function like that this.props.searchLocationChange(this.state.searchText)

You can do something like below

 <div className="search-form__submit"><button onClick={() => {this.props.searchLocationChange(this.state.searchText)}}>Search</button></div>

and function definition should be

searchLocationChange(searchText) {

Upvotes: 1

simbathesailor
simbathesailor

Reputation: 3687

You are mixing controlled and uncontrolled. Either do controlled or uncontrolled. So take the search Text from parent only. Above solutiion is one way of doing this . Another way is to pass searchTxt from parent to child.

<SearchForm 
   searchTxt={this.state.searchTxt}
   handleInputChange={this.handleInputChange}
   searchLocationChange={this. searchLocationChange}
/>

Move your handleInputChange in parent:

handleInputChange = (event) => {
    const enteredText = event.target.value;
    this.setState({ searchText: enteredText });
  }

Then change your child component respective line to

 <div className="search-form__input"><input type="text" value={this.props.searchText} onChange={this.props.handleInputChange} /></div>

Now when you try the above code it should work. Now you are keeping your searchTxt in the parent component. your SearchForm component is Completely controlled now.

Upvotes: 0

Sakhi Mansoor
Sakhi Mansoor

Reputation: 8102

You're already passing down searchLocationChange from your parent.

in parent component:

searchLocationChange(searchedText) {
console.log(searchText);
Axios.get('https://mcr-codes-weather.herokuapp.com/forecast', {
  params: {
    city: searchText,
  },
})
  .then((response) => {
    this.setState({
      forecasts: response.data.forecasts,
      location: {
        city: response.data.location.city,
        country: response.data.location.country,
      },
    });
  });
}

in child:

render() {
 const { searchText } = this.state;
    return (
      <span className="search-form">
        <div className="search-form__input"><input type="text" value={this.state.searchText} onChange={this.handleInputChange} /></div>
        <div className="search-form__submit"><button onClick={()=>{this.props.searchLocationChange(searchText)}}>Search</button></div>

      </span>
    );
  }

Upvotes: 2

Related Questions