Alex Erling
Alex Erling

Reputation: 307

Search results not updating after second search - REACT

I set up a search bar, and after I search the results will pop up. However, the issue is, if I don't refresh the page and search again, it will push me to the new search, but the search results won't update with it. Why would the updated param be showing even though the results aren't updating?

Ex. first url is search/erl,second url is search/Groovy%20Playlist

First search

First search

Second search, query param updated, but search results didn't

Second search

Searchbar.js

class SearchBar extends Component {
  constructor(props) {
    super(props)
    this.state = {query: '', results: [], isLoading: false}
  }

  componentWillMount() {
     this.resetComponent()
   }

   resetComponent = () => this.setState({ isLoading: false, results: [], query: '' })

   search(query) {
     this.setState({ query });
     axios
       .get(`/api/search?query=${query}`)
       .then(response => {
         this.setState({ results: response.data});
       })
       .catch(error => console.log(error));
   }

   handleFormSubmit = () => {
   console.log('search:', this.state.query);
   this.props.action
   this.props.history.push(`/search/${this.state.query}`)
   this.resetComponent()



 }


  handleInputChange = (query) => {
    this.search(query);
    this.setState({ isLoading: true, query })

    setTimeout(() =>
      this.setState({
        isLoading: false,
      }) , 300)

  }

  handleResultSelect = (e, { result }) => this.setState({ query: result.title}  )

  render () {

    const resultRenderer = ({ title }) => <List content = {title}/>
    return (

      <Form onSubmit={this.handleFormSubmit}>
      <Search
        loading={this.state.isLoading}
        onResultSelect={this.handleResultSelect}
        onSearchChange={(event) => {this.handleInputChange(event.target.value)}}
        showNoResults={false}
        value={this.state.query}
        resultRenderer={resultRenderer}
        results ={this.state.results}
        type={"submit"}
        { ...this.props}  />
      </Form>

    );
  }

}


export default withRouter (SearchBar)

Search.js

class Search extends Component {
  constructor(props) {
    super(props)
    this.state = {
      results: []
    }
  }

  componentWillMount() {
    const { match: { params } } = this.props;
    axios
      .get(`/api/search?query=${params.query}`)
      .then(response => {
        console.log(response);
        this.setState({ results: response.data });
      })
      .catch(error => console.log(error));
  }


    render() {
         console.log(this.state.results)
      return(

        <div>
          <div className = "heading centered">
            <h1> Search results for: {this.props.match.params.query} </h1>
          </div>
          {this.state.results.map((post) => {
            return(
                <Post key = {post.id} post={post}/>

            )
          })}
        </div>
      );

    }
}

export default Search

Upvotes: 4

Views: 2461

Answers (1)

Jonas Wilms
Jonas Wilms

Reputation: 138307

Updating results of the SearchBars state will be passed down to Search's props, but you don't work with this.props.results but rather with this.state.results, and that doesnt get updated even if the props change. That works the first time as you reload the Search's state inside componentWillMount but that doesnt get called again as the component is not remounted. Therefore Search always works with its states results, that are never updated.

Now to solve this chaos, remove the componentWillMount logic from Search as that is actually doing what SearchBar already does, and add a listener to componentWillReceiveProps that updates the Searches state, or don't work with the state at all inside Search but take the passed in results instead as this.props.results.

  const Search = ({ match, results }) => (
    <div>
      <div className = "heading centered">
        <h1> Search results for: {match.params.query} </h1>
      </div>
      {results.map((post) => 
            <Post key = {post.id} post={post}/>
      )}
   </div>
  );

Upvotes: 1

Related Questions