Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

React passing data to child from parent

Hello,

I am trying to complete a challenge using react.js. I am not sure how to pass data from the App.js to the next component GlacierNational.js. I tried using the routes and calling render and then the component but no props or data seems to pass inside it?

I am not sure the best way to pass props to the child component so it can render the new data. I know this not a DRY approach but I am also a little foggy on the best architecture for how to layout the code.

App.js

import React, { Component } from 'react';
import axios from 'axios';


import './App.css';

import apiKey from './Config';

import Search from './Search';
import Nav from './Nav';
import PhotoList from './PhotoList';
import PhotoContainer from './PhotoContainer';

import GlacierNational from './GlacierNational';

import {
  NavLink,
  BrowserRouter,
  Switch,
  Route
} from 'react-router-dom';


class App extends Component {

  constructor() {
    super();
    this.state = {
      photos: [],
      loading: true
    };
  }

  componentDidMount() {
    this.performSearch();
  }

  performSearch = (urlQuery) => {

    let query = (urlQuery) ? urlQuery : 'canadian rockies';
    console.log('urlQuery = ', urlQuery);
    console.log('query = ',query);

    axios.get(`https:api.flickr.com/services/rest/?method=flickr.photos.search&api_key=${apiKey}&tags=${query}=&per_page=24&format=json&nojsoncallback=1`)      
    .then(response => {
      this.setState({
        photos: response.data.photos.photo,
        loading: false
      });
    })
    .catch(function(error){
      console.log(error);
    });
  }

  render() {
    return (
      <BrowserRouter>
        <div className="container">
            <Switch>
              <Route path="/search" render={() => (
                <Search onSearch={this.performSearch} />
              )} />   
              <Route path="/search/isle-royale"  />
              <Route path="/search/glacier-national"  render={() => ( <GlacierNational  /> ) }  /> 
              <Route path="/search/glacier-bay"  />     
            </Switch>             

            <Nav />

            <div className="photo-container">
                  <h2>Results</h2>
                  {
                    (this.state.loading)
                    ? <p> Loading search results ....</p>
                    : <PhotoList  data={this.state.photos} /> 
                  }                  
            </div>                        
        </div>
      </BrowserRouter>
    );
  }
}

export default App;

Glacier

import React, { Component } from 'react';
import { NavLink, Route } from 'react-router-dom'; 
import Search from './Search';
import axios from 'axios';

import logo from './logo.svg';
import './App.css';

import apiKey from './Config';
import PhotoContainer from './PhotoContainer';

import PhotoList from './PhotoList';

class GlacierNational extends Component {

    constructor() {
        super();
        this.state = {
          photos: [],
          loading: true
        };
    }

    componentDidMount() {
        this.performSearch("glacier national park");
    }

    performSearch = (tags) => {

        axios.get(`https:api.flickr.com/services/rest/?method=flickr.photos.search&api_key=${apiKey}&tags=${tags}=&per_page=24&format=json&nojsoncallback=1`)      
        .then(response => {
          this.setState({
            photos: response.data.photos.photo,
            loading: false
          });
        })
        .catch(function(error){
          console.log(error);
        });
    }

    render() {
        return ( 
            <div className="photo-container">
                  <h2>Glacier</h2>
                  {
                    (this.state.loading)
                    ? <p> Loading search results ....</p>
                    : <PhotoList  data={this.state.photos} /> 
                  }                  
            </div>              
        );
    }


}

export default GlacierNational;

1 Answer

I ended up refactoring a lot of this....

I used a separate component for the photos and then just used the url to do the search by getting the match object and params. It seems to work now.

        <BrowserRouter>
            <div className="container">                
                <Switch>
                    <Route exact path="/" component={PhotoList}   />   
                    <Route exact path="/search" component={Search}  />   
                    <Route path="/search/:tags"  component={PhotoList} />   
                    <Route component={NotFound} /> 
                </Switch> 
            </div>
        </BrowserRouter>