javascript reactjs react-router react-router-v4 query-parameters

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