user2932090
user2932090

Reputation: 331

ReactJS - passing data from a child component to its parent

I have the following structure of components in the application:

class Car extends Component {
    constructor() {
        super();
        this.state = {
            cars: [],
            ...
        }
    }
    componentDidMount() {
        axios.get('/api/cars')
            .then((response) => {
                this.setState({cars: response.data});
                console.log('cars: ', cars);
            }).catch(err => {
                console.log('CAUGHT IT! -> ', err);
            });
    }
    render() {
      return (
        ...
        <CarAddNew />
        <CarSearch />
        <CarList cars={this.state.cars} />
      )
    }
}

and then

export default class CarSearch extends Component {
    constructor(){...}
    handleSearchSubmit(e) {
        e.preventDefault();
        ..
        axios.post('/api/cars/search', searchCars)
            .then(response => {
                console.log('response.data: ', response.data);
            })
    }
    render() {
        return(
          ... search form ...
        )
    }

When I search data in the database through the CarSearch component, it will fetch and load the right data, that's great. However, how do I pass this "new" found data to the CarList component, so I can display the on the page?

Upvotes: 1

Views: 651

Answers (2)

scniro
scniro

Reputation: 16979

One option is to propagate the data up through a prop on CarSearch. Consider the (truncated) example...

handleSearchSubmit(e) {
  e.preventDefault();
  axios.post('/api/cars/search', searchCars).then(response => {
    this.props.onData(response.data);
  });
}

where, onData calls back up to the following (then later setting state)...

constructor() {
  // [...]
  this.onSearchResult = this.onSearchResult.bind(this);
}

onSearchResult(cars) {
  this.setState({cars}); // results from CarSearch
}

render() {
  return (
    <CarAddNew />
    <CarSearch 
      onData={this.onSearchResult} />
    <CarList 
      cars={this.state.cars} />
  )
}

Upvotes: 2

crumbug
crumbug

Reputation: 438

What I would do is the following:

class Car extends Component {
    constructor() {
        super();
        this.state = {
            cars: [],
            ...
        }
    }
    componentDidMount() {
        axios.get('/api/cars')
            .then((response) => {
                this.setState({cars: response.data});
                console.log('cars: ', cars);
            }).catch(err => {
                console.log('CAUGHT IT! -> ', err);
            });
    }
    handleSearch = () => {
        axios.post('/api/cars/search', searchCars)  // not sure where you are getting searchCars from, but you should get the idea
            .then(response => {
                this.setState({cars: response.data})
                console.log('response.data: ', response.data);
            })
    }

    render() {
      return (
        ...
        <CarAddNew />
        <CarSearch onSearch={this.handleSearch} />
        <CarList cars={this.state.cars} />
      )
    }
}


export default class CarSearch extends Component {
    constructor(){...}
    handleSearchSubmit(e) {
        e.preventDefault();
        this.props.onSearch() // I'm assuming you probably want to pass something here
    }
    render() {
        return(
          ... search form ...
        )
    }

Upvotes: 4

Related Questions