React 路由器渲染两次并通过删除所有查询参数来更改 URL

React router rendering twice and URL changes by dropping all query parameters

我正在使用 BrowserRouterhistory.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