4

I am trying to create a search page in an application with several pages, I use react router v5.

My problem is the following, I would like to return to the previous page when a text field is empty otherwise if there is an entry in the input field, I want to return to the search page ('/search')

I thank you in advance for your help and your answers.

So I used goBack and push props. But the return to the previous page does not work even when the field is empty

My component Routes.js

 const Routes = (props) => {
    return (
       <div>
          <Route exact path="/" component={Home} />
          <Route
             exact
             path='/search'
             component={() => <Search query={props.text} />}
          />
          <Route path="/film/:id" component={MovieDetail} />  
          <Route path="/FavorisList" component={WatchList} />
          <Route path="/search/:search" component={Search} />
          <Route path="*" component={NotFound} />  
       </div>

  )}

My component SearchBar.js

  class SearchBar extends React.Component {
      constructor(props) {
         super(props);

         this.state = {
            inputValue:'',
         };

       }

      handleChange = (event) => {

          if(event.target.value === '') {
              this.props.history.goBack()
              return;
          }

          if(event.target.value.length){
             this.props.history.push("/search")
             this.search(event.target.value)
          }
       }

       search = (query) => {
           //search results retrieved with redux 
           this.props.applyInitialResult(query, 1)
       }

       render() {
          return (
            <div>
               <input
                   type="text"
                   value={this.state.inputValue}
                   placeholder="Search movie..."
                   className={style.field}
                   onChange={this.handleChange.bind(this)}
               />  
            </div>
          );
        }


       export default SearchBar;

Component App.js

       class App extends React.Component {
          render(){
              return (
                 <div>
                    <BrowserRouter>
                       <NavBar />
                       <Routes/>
                    </BrowserRouter>
                 </div>
              );
           }
        }

        export default App;
Raiden-x
  • 73
  • 1
  • 5

1 Answers1

0

I think the problem is that you push new entry to history on every change event. So if you e.g. enter 3 characters then 3 the same entries are pushed to history stack. As a result when you then call history.goBack it redirects to previous entry in history stack which is /search in your case (so you remain on the current page).

You can think of history stack as array which holds entries - when you have entered 3 characters this array will look like this: ['/someInitialPath', '/search', '/search', '/search'] Calling goBack redirects to previous path in history stack so if you now call goBack you get the path pointing to the /search path which is current page and as a result you see no change. You would get redirected to /someInitialPath if you called goBack 3 times in this case.

Solution is to call history.push only on first change event. You can add additional field to state indicating whether handleChange is called for the first time. Something like this:

class SearchBar extends React.Component {
     constructor(props) {
         super(props);

         this.state = {
            inputValue:'',
            initialChange: true
         };

      }

      handleChange = (event) => {

          if(event.target.value === '') {
              this.props.history.goBack()
              this.setState({ initialChange: true }) // clear flag after redirect
              return;
          }

          if(event.target.value.length && this.state.initialChange){
             this.setState({
               initialChange: false
             }, () => {
               this.props.history.push("/search")
               this.search(event.target.value)
             })

          }
       }
    ... 
}
Bartek Fryzowicz
  • 6,464
  • 18
  • 27
  • Yes I think you're right, but how can I prevent this page change at every event on Change. If this can help you, I want to reproduce what netflix do for their search system, I do not know if react router is the best solution. – Raiden-x Aug 13 '19 at 17:40
  • I've updated answer with draft of solution. React-router is good choice, actually your problem is not caused by this or other lib so it doesn't matter if you use react-router or any other routing lib. But react-router is most popular lib for this. Detailed solution might be more complex but it depends on other requirements. But I do hope my answer solves problem from your question. – Bartek Fryzowicz Aug 13 '19 at 17:48
  • Hello I just tried your solution, it works the first time, but as I want to do a new search, I do not return to the search page. – Raiden-x Aug 13 '19 at 17:58
  • I've just updated with improved version (added clearing flag). Please try this. – Bartek Fryzowicz Aug 13 '19 at 17:59
  • Oh thank you very much! it works, so I have another concern now, how can I save the state of my search page, when I refresh the application, I stay on my search page but I lost my search results and the value of my input fields. – Raiden-x Aug 13 '19 at 18:07
  • Great :) So please accept my answer and upvote it please. I'm sorry but you have to create new SO post with your question because this is something not related with your orignal question. One answer per question - this is how SO works. I can't answer all your concerns in one post and in comments. – Bartek Fryzowicz Aug 13 '19 at 18:11
  • 1
    I have already put a vote, I will create a new post for this question. – Raiden-x Aug 13 '19 at 18:13
  • Thank you :) I'm glad I could help you. – Bartek Fryzowicz Aug 13 '19 at 18:14
  • I created a new post for my second question, again thanks for your help => https://stackoverflow.com/questions/57483582/how-to-update-the-url-of-a-page-using-an-input-field – Raiden-x Aug 13 '19 at 18:35