Detect change in query param react-router-dom v4.x and re-render component

亡梦爱人 提交于 2019-11-27 05:34:48

React router from v4 onwards no longer gives you the query params in its location object. The reason being

There are a number of popular packages that do query string parsing/stringifying slightly differently, and each of these differences might be the "correct" way for some users and "incorrect" for others. If React Router picked the "right" one, it would only be right for some people. Then, it would need to add a way for other users to substitute in their preferred query parsing package. There is no internal use of the search string by React Router that requires it to parse the key-value pairs, so it doesn't have a need to pick which one of these should be "right".

Having included that, It would just make more sense to just parse location.search in your view components that are expecting a query object.

You can do this generically by overriding the withRouter from react-router like

customWithRouter.js

import { compose, withPropsOnChange } from 'recompose';
import { withRouter } from 'react-router';
import queryString from 'query-string';

const propsWithQuery = withPropsOnChange(
    ['location', 'match'],
    ({ location, match }) => {
        return {
            location: {
                ...location,
                query: queryString.parse(location.search)
            },
            match
        };
    }
);

export default compose(withRouter, propsWithQuery)

and wherever you need query string, you could simply use it like

import withRouter from 'path/to/customWithRouter.js';

class Home extends Component {
  constructor(props) {
    super(props);
    console.log('-!!!')
    this.state = {
      step: 1,
    }
    this.next = this.next.bind(this);
  }

  next(stepNumber=1) {
    this.props.history.push({
      pathname: `/adamchenwei/pen/YeJBxY?editors=0011&step=${stepNumber}`,
    });
  }
  componentDidUpdate(prevProps) {    // using componentDidUpdate because componentWillReceiveProps will be renamed to UNSAFE_componentWillReceiveProps from v16.3.0 and later removed
    const {query: { step } } = this.props.history.location;
    if(!_.isEqual(this.props.history.location.query, prevProps.history.location.query)) {
         this.setState({
             step
          })
    }
  }
  render() {
    console.log('render!!!');
    console.log(this);
    const {
      step
    } = this.state;
    console.log('---step');
    console.log(step);
    return(
      <div>
        <h1>Welcome to the Tornadoes Website!</h1>
        <button onClick={()=> this.next(1)} > Step 1</button>
        <button onClick={()=> this.next(2)} > Step 2</button>
        {
          step === 1 ? <h1>Step 1 here</h1> : null
        }
        {
          step === 2 ? <h1>Step 2 here</h1> : null
        }
      </div>

    );
  }
}

const HomeWithQuery = withRouter(Home);

// A lose explanation. URL = localhost:3000/myRoute/2

<Router history={history}>
  <Route path="/myRoute/:id" component={App} />
</Router>

class App extends Component {
  render() {
    const { id } = this.props.match.params
    
    return (
      <div>
        {id === 2 ? <div>id is 2</div> : <div>id not 2</div>}
      </div>
    )
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!