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