3

In my main class I have a nav bar with the options below:

          <NavDropdown title="Search" id="collasible-nav-dropdown">
            <NavDropdown.Item href="#/searchpage/p" onClick={this.dontEdit}>Find People</NavDropdown.Item>
            <NavDropdown.Item href="#/searchpage/s" onClick={this.searchSchool}>Find Schools</NavDropdown.Item>
            <NavDropdown.Item href="#/searchpage/w" onClick={this.dontEdit}>Find Work Places</NavDropdown.Item>
          </NavDropdown>

These have a route which routes to the same component which then reads the parameter at the end of the URL and runs a different search depending on the value. For example 's' is search schools and 'p' is search people. If I navigate between the different search functions from the nav bar then it doesn't refresh to the new search. For example if I go from 'Find Schools' to 'Find Work' it stays on schools, but if I were to go direct to 'Find Work Places' then it goes there direct. Also if I navigate to the home page and back to another search then it works.

The route looks like:

<Route path="/searchpage/:type"  render={props => (<SearchPage {...props} findPerson={this.findPerson} routeReset={this.routeReset} getPersonsByName={this.getPersonsByName} />)}/>

Is anyone able to advise how to get this to route as I want it to? The search component is like:

import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Container from 'react-bootstrap/Container';
import Button from 'react-bootstrap/Button';

import Flash from './components/flash';
import Search from "./components/search";

const searchtypes = {"p":"People","w":"Work Places","s":"Schools"};

class SearchPage extends Component {



  constructor(props) {
    super(props);

    this.state = {
      type:this.props.match.params.type
    }
  }

  componentDidMount(){

  }


  render() {
    return (
      <Container>
        <Row>
          <Col>
            <h4>Search {searchtypes[this.state.type]}</h4>
            <br/>
          </Col>
        </Row>
        <Row><Col><Search {...this.props} type={this.state.type}/></Col></Row>
      </Container>
    );
  }
}

export default SearchPage;
1
  • Could you attach a link to a codesandbox? i'm not sure i'm entirely able to understand the question Commented Jan 18, 2020 at 19:26

2 Answers 2

5

The Route's render prop doesn't remount when the matched route doesn't change, i.e. even when the route matches but the route param is different it won't re-render. Instead use the component prop.

react-router-dom component

When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop (below).

<Route
  path="/searchpage/:type"
  component={props => (
    <SearchPage
      {...props}
      findPerson={this.findPerson}
      routeReset={this.routeReset}
      getPersonsByName={this.getPersonsByName}
    />
  )}
/>

An alternative to this is to implement the componentDidUpdate lifecycle function in SearchPage to detect when the route param prop updates and update the type stored in state. This way the component won't continually unmount/mount each time.

componentDidUpdate(prevProps) {
  if (prevProps.match.params.type !== this.props.match.params.type) {
    setState({
      type: this.props.match.params.type,
    });
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Many thanks, I used the second solution using the life cycle method and it is working fine.
0

Try this:

class SearchPage extends Component {

  render() {
    return (
      <Container>
        <Row>
          <Col>
            <h4>Search {searchtypes[this.props.match.params.type]}</h4>
            <br/>
          </Col>
        </Row>
        <Row><Col><Search {...this.props} type={this.props.match.params.type}/></Col></Row>
      </Container>
    );
  }
}

The type data comes from props and therefore you should not persist it on the component state. Note: Make sure you use react-router Link component it seems you use native a tags

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.