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

Lance Chandler
seal-mask
PLUS
.a{fill-rule:evenodd;}techdegree seal-36
Lance Chandler
Front End Web Development Techdegree Graduate 21,818 Points

Project 11 - Search Component - TypeError:_this.performSearch is not a function

I am trying to call the function: performSearch or even better the component: FetchContainer when text is typed into the "Search" field on the form:

TypeError: _this.performSearch is not a function Search._this.handleSubmit src/components/Search.js:25 22 | // Input field's value 23 | let checkquery = (this.query.value); 24 | console.log('You typed "'+ checkquery + '" in the Search field');

25 | this.performSearch(this.query.value); 26 | e.currentTarget.reset(); 27 | } 28 |

Search.js: // Search input Text & Maginfying Glass button import React, { Component } from 'react';

//import Apps import FetchContainer from './FetchContainer';

export default class Search extends Component { // State specific for this component that is updated // by onSearchChange function that users type Text // into input field of the Form state = { searchText: '' }

onSearchChange = e => { this.setState({ searchText: e.target.value }); }

// Function that is called when the Form is submitted handleSubmit = e => { e.preventDefault(); // Input field's value let checkquery = (this.query.value); console.log('You typed "'+ checkquery + '" in the Search field'); this.performSearch(this.query.value); e.currentTarget.reset(); }

render() { return ( <div> <form className="search-form" onSubmit={this.handleSubmit} > <input type="search" onChange={this.onSearchChange} name="search" ref={(input) => this.query = input} // Puts a reference to the input on the Search form class placeholder="Search" /> <button type="submit" className="search-button"> <svg fill="#fff" height="24" viewBox="0 0 23 23" width="24" xmlns="http://www.w3.org/2000/svg"> <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/> <path d="M0 0h24v24H0z" fill="none"/> </svg> </button> </form> </div> ); } }

FetchContainer.js: // Container component that takes in a keyword and api key as props // and fetches the photos and other required information from the API import React, { Component } from 'react';

// a promised-based library that makes server requests in React // It will ne used to fetch the data from Flickr import axios from 'axios';

// import api_key assigned from Flickr Website located in Config.js // to be used with the Axios 'get' statement import apiKey from './Config' ;

// App components import PhotoContainer from './PhotoContainer';

export default class FetchContainer extends Component { // Initialize State for data that is going to change constructor() { super(); this.state = { // State is the 'photos' data we want to display photos: [], loading: true, query: '' }; }

// componentDidMount is used to "fetch data from a server" with AJAX calls (axios will perform) componentDidMount() { // axios (get method) - uses Javascript Promises to handle results. Promises let you chain methods (callbacks) in a sequential order // URL is a Template Literal so we can embed the values of: apikey & query axios.get(https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=${apiKey}&text=${this.props.query}&per_page=16&format=json&nojsoncallback=1) // Response object executed once results are obtained from Flickr .then(response => { this.setState({ photos: response.data.photos.photo, loading: false, query: '' }); }) // catch method - handles any errors fetching data .catch(error => { console.log('Error fetching and parsing data', error); }); }

performSearch = (query) => { axios.get(https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=${apiKey}&text=${this.props.query}&per_page=16&format=json&nojsoncallback=1) // Response object executed once results are obtained from Flickr .then(response => { this.setState({ photos: response.data.photos.photo, loading: false }); }) // catch method - handles any errors fetching data .catch(error => { console.log('Error fetching and parsing data', error); }); }

render() { console.log(this.state.photos); return ( <div className="photo-container"> { (this.state.loading) ? <p>Loading...</p> : <PhotoContainer data={this.state.photos} /> } </div> ); } }

Totally stumped on how to proceed. Been trying for days. Any guidance would be greatly appreciated.

2 Answers

Steven Parker
Steven Parker
231,007 Points

Your "handleSubmit" callback is implemented as an arrow function, and one of the differences between those and conventional functions is that they do not establish a value for "this".

But since you have the passed-in event object as "e", you can substitute "e.target" instead.