React 路由器渲染两次并通过删除所有查询参数来更改 URL
React router rendering twice and URL changes by dropping all query parameters
我正在使用 BrowserRouter
和 history.push
在页面之间导航。我想遍历到一个新的页面,在第一页输入查询参数。
也就是说,在主页中,有一个搜索栏,用户可以在其中输入一些搜索字符串 abc
,当单击该按钮时,我想重定向到另一个页面 /search?q=abc
我观察到的是,/search?q=abc
正确呈现一次,然后它自动重定向到 /search?
,删除所有查询参数。我无法理解为什么它会渲染两次?
包
"react": "^16.12.0",
"react-bootstrap": "^1.0.0-beta.16",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
App.js
import React, { Component} from 'react';
import './App.css';
import {BrowserRouter as Router, Route} from 'react-router-dom';
import Jumbotron from "./component/Jumbotron";
const SearchPage = ({ match, location }) => {
return (
<p>
<strong>Query Params: </strong>
{location.search}
</p>
);
};
const HomePage = () => {
return (
<div className="d-flex flex-column">
<div className="container-fluid">
<Jumbotron/>
</div>
</div>
)
};
class App extends Component {
render() {
return (
<Router>
<Route exact={true} path='/' render={HomePage}/>
<Route exact path="/search" render={SearchPage} />
</Router>
);
}
}
export default App;
Jumbotron.jsx <- 这是第一个包含搜索栏的页面
import React, { Component } from 'react';
import { withRouter } from 'react-router';
import history from "../utils/history";
class Jumbotron extends Component {
handleSubmit = () => {
history.push({
pathname: '/search',
search: '?q=' + this.state.query
})
};
handleChange = e => {
this.setState({query: e.target.value});
console.log(e.target.value)
};
render() {
return (<>
<div className="d-flex jumbotron">
<div className="align-self-center container mx-auto">
<br/>
<div>
</div>
<div className="align-self-center">
<form className="d-flex justify-content-center form-inline my-2 my-lg-0">
<input className="search-input col-md-6 mb-3 form-control"
type="search"
placeholder="Type the address here"
aria-label="Search"
onChange={this.handleChange}
/>
<button className="search-btn col-md-1 mb-3 btn btn-primary"
onClick={this.handleSubmit}>Search
</button>
</form>
</div>
</div>
</div>
</>
)
}
}
export default withRouter(Jumbotron);
history.js
import { createBrowserHistory } from "history";
export default createBrowserHistory();
我在这里错过了什么?
更新
下面是描述行为的上述代码示例:
https://codesandbox.io/s/blissful-fermat-60xzy
2 种解决问题的方法:
第一个解法:
- 导入
Router
而不是 BrowserRouter
- 将您在
./history.js
中定义的 history
传递给 Router
。像这样<Router history={history}>
- 现在
history.push({.....
应该可以正常工作了。
第二种方案:
- 进口
BrowserRouter
- 用
withRouter
包装 Jumbotron
组件
- 使用
this.props.history.push(...)
代替history.push(...)
您的代码(第一个解决方案)的工作副本在这里:
https://codesandbox.io/s/router-issue-page-refresh-after-search-hl849?file=/src/App.js
我正在使用 BrowserRouter
和 history.push
在页面之间导航。我想遍历到一个新的页面,在第一页输入查询参数。
也就是说,在主页中,有一个搜索栏,用户可以在其中输入一些搜索字符串 abc
,当单击该按钮时,我想重定向到另一个页面 /search?q=abc
我观察到的是,/search?q=abc
正确呈现一次,然后它自动重定向到 /search?
,删除所有查询参数。我无法理解为什么它会渲染两次?
包
"react": "^16.12.0",
"react-bootstrap": "^1.0.0-beta.16",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
App.js
import React, { Component} from 'react';
import './App.css';
import {BrowserRouter as Router, Route} from 'react-router-dom';
import Jumbotron from "./component/Jumbotron";
const SearchPage = ({ match, location }) => {
return (
<p>
<strong>Query Params: </strong>
{location.search}
</p>
);
};
const HomePage = () => {
return (
<div className="d-flex flex-column">
<div className="container-fluid">
<Jumbotron/>
</div>
</div>
)
};
class App extends Component {
render() {
return (
<Router>
<Route exact={true} path='/' render={HomePage}/>
<Route exact path="/search" render={SearchPage} />
</Router>
);
}
}
export default App;
Jumbotron.jsx <- 这是第一个包含搜索栏的页面
import React, { Component } from 'react';
import { withRouter } from 'react-router';
import history from "../utils/history";
class Jumbotron extends Component {
handleSubmit = () => {
history.push({
pathname: '/search',
search: '?q=' + this.state.query
})
};
handleChange = e => {
this.setState({query: e.target.value});
console.log(e.target.value)
};
render() {
return (<>
<div className="d-flex jumbotron">
<div className="align-self-center container mx-auto">
<br/>
<div>
</div>
<div className="align-self-center">
<form className="d-flex justify-content-center form-inline my-2 my-lg-0">
<input className="search-input col-md-6 mb-3 form-control"
type="search"
placeholder="Type the address here"
aria-label="Search"
onChange={this.handleChange}
/>
<button className="search-btn col-md-1 mb-3 btn btn-primary"
onClick={this.handleSubmit}>Search
</button>
</form>
</div>
</div>
</div>
</>
)
}
}
export default withRouter(Jumbotron);
history.js
import { createBrowserHistory } from "history";
export default createBrowserHistory();
我在这里错过了什么?
更新
下面是描述行为的上述代码示例: https://codesandbox.io/s/blissful-fermat-60xzy
2 种解决问题的方法:
第一个解法:
- 导入
Router
而不是BrowserRouter
- 将您在
./history.js
中定义的history
传递给Router
。像这样<Router history={history}>
- 现在
history.push({.....
应该可以正常工作了。
第二种方案:
- 进口
BrowserRouter
- 用
withRouter
包装 - 使用
this.props.history.push(...)
代替history.push(...)
Jumbotron
组件
您的代码(第一个解决方案)的工作副本在这里:
https://codesandbox.io/s/router-issue-page-refresh-after-search-hl849?file=/src/App.js