webentwicklung-frage-antwort-db.com.de

Erkennen Sie Änderungen in Abfrageparameter Reakt-Router-Dom v4.x und stellen Sie die Komponente erneut dar

Ich bin nicht wirklich sicher, warum es die Standardroute zeigt, nachdem ich eine Abfrageparameteränderung vorgenommen habe. Gibt es einen besseren Ansatz für diese Art von Problem? Vielleicht sollte ich nicht Abfrageparameter verwenden? Offen für die Ausbildung!

Version "Reagieren": "^ 16.2.0", "Reaktom": "^ 16.2.0", "Reaktiver Router": "^ 4.2.0", "reag-router-dom": "^ 4.2.2",


Test Case https://codepen.io/adamchenwei/pen/YeJBxY?editors=0011

Schritte zum ReproduzierenKlicken Sie auf Home -> Schritt 1

Erwartetes Verhalten Fahren Sie mit Schritt 1 fort, und machen Sie mit Schritt 2 den korrekten Dom wieder

Tatsächliches Verhalten Leer, nichts wird auf der Seite dargestellt

// For this demo, we are using the UMD build of react-router-dom
const {
  BrowserRouter,
  Switch,
  Route,
  Link
} = ReactRouterDOM

const {
  Component,
} = React;

const Router = BrowserRouter;

const Step1View = () => (
  <div>
    <h1> Step 1</h1>
  </div>
)

const Step2View = () => (
  <div>
    <h1> Step 2</h1>
  </div>
)

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}`,
    });
    const query = this.props.history.location.pathname;
    console.log('---aaaaa');
    console.log(query);
    if (query === '/adamchenwei/pen/YeJBxY?editors=0011/?step=1') {
      this.setState({
        step: 1,
      })
    } else if (query === '/adamchenwei/pen/YeJBxY?editors=0011/?step=2') {
      this.setState({
        step: 2,
      })
    }
  }
  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>

    );
  }
}

// The Main component renders one of the three provided
// Routes (provided that one matches). Both the /roster
// and /schedule routes will match any pathname that starts
// with /roster or /schedule. The / route will only match
// when the pathname is exactly the string "/"
const Main = () => (
  <main>
    <Route exact path='/' component={Home}/>
  </main>
)

// The Header creates links that can be used to navigate
// between routes.
const Header = () => (
  <header>
    <nav>
      <ul>
        <li><Link to='/'>Home</Link></li>
        <li><Link to='/roster'>Roster</Link></li>
        <li><Link to='/schedule'>Schedule</Link></li>
      </ul>
    </nav>
  </header>
)

const App = () => (
  <div>
    <Header />
    <Main />
  </div>
)

// This demo uses a HashRouter instead of BrowserRouter
// because there is no server to match URLs
ReactDOM.render((
  <Router>
    <App />
  </Router>
), document.getElementById('root'))
8
Ezeewei

Reagieren Sie den Router ab Version 4 nicht mehr mit den Abfrageparametern in seinem Standortobjekt. Der Grund dafür ist

Es gibt eine Reihe von gängigen Paketen, die die Zeichenfolge parsing/stringifying etwas anders abfragen. Jeder dieser Unterschiede kann für einige Benutzer die "correct"-Methode sein, für andere wiederum "incorrect". Wenn React Router den "right" eins auswählte, wäre dies nur für einige Leute richtig. In diesem Fall müssten andere Benutzer die Möglichkeit erhalten, ihr bevorzugtes Paket zur Abfrageanalyse zu ersetzen. Die Suchzeichenfolge wird von React Router nicht intern verwendet, sodass die Schlüssel-Wert-Paare analysiert werden müssen. Daher muss nicht ausgewählt werden, welches der beiden "richtig" sein sollte.

Nach dem Hinzufügen wäre es nur sinnvoller, location.search in Ihren Ansichtskomponenten zu analysieren, die ein Abfrageobjekt erwarten.

Sie können dies generisch tun, indem Sie den withRouter vom Reakt-Router überschreiben

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)

und wo immer Sie Abfragezeichenfolge benötigen, können Sie es einfach wie verwenden

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);
3
Shubham Khatri

// 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>
    )
  }
}

1
Francis Leigh