javascript - Detectar cambios en el parámetro de consulta react-router-dom v4.xy volver a procesar el componente
reactjs react-router-v4 (2)
No estoy realmente seguro de por qué muestra la ruta predeterminada una vez que hice un cambio de parámetro de consulta. ¿Existe un mejor enfoque para este tipo de problema? tal vez no debería estar usando el parámetro de consulta? ¡Abierto para educarse!
Versión "react": "^ 16.2.0", "react-dom": "^ 16.2.0", "react-router": "^ 4.2.0", "react-router-dom": "^ 4.2. 2 ",
Caso de prueba https://codepen.io/adamchenwei/pen/YeJBxY?editors=0011
Pasos para reproducir Haga clic en Inicio -> Paso 1
Comportamiento esperado Vaya al Paso 1 y al Paso 2 renderice el dom correcto
Comportamiento real vacío, no se muestra nada en la página
// 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''))
Reaccionar enrutador desde v4 en adelante ya no le da los parámetros de consulta en su objeto de ubicación. La razón es
Hay una serie de paquetes populares que
parsing/stringifying
cadenas de consultas de
parsing/stringifying
ligeramente diferente, y cada una de estas diferencias puede ser la forma
"correct"
para algunos usuarios e
"incorrect"
para otros.
Si
React Router
eligió el
"right"
, solo sería adecuado para algunas personas.
Luego, necesitaría agregar una forma para que otros usuarios sustituyan en su paquete de análisis de consultas preferido.
No hay uso interno de la cadena de búsqueda por React Router que requiera analizar los pares clave-valor, por lo que no es necesario elegir cuál de estos debe ser "correcto".
Una vez incluido eso, tendría más sentido simplemente analizar
location.search
en los componentes de la vista que esperan un objeto de consulta.
Puede hacer esto genéricamente anulando withRouter desde react-router como
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)
y donde sea que necesite una cadena de consulta, simplemente puede usarla como
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>
)
}
}