我有一个简单的 Navbar
,里面有一个 Form
:
const NavBar = () => {
let history = useHistory()
...
...
return (
...
<Form inline onSubmit={handleSubmit}>
<InputGroup style={{width: "90%"}}>
<Form.Control id="navbar-search" placeholder="Pesquise" size="sm"/>
<Form.Control as="select" size="sm">
<option>Ações</option>
<option>Declarações</option>
</Form.Control>
<InputGroup.Append size="sm">
<Button size="sm" type="submit" variant="outline-secondary">
<SearchIcon fontSize="small" />
</Button>
</InputGroup.Append>
</InputGroup>
</Form>
...
)
handleSubit
假设重定向(使用 history.push
)到我将使用输入值作为搜索参数的路径。我正在使用 react-router-dom
。
const handleSubmit = (e) => {
let baseEndpoint = e.target[1].value === "Ações" ? "actions" : "quotes"
history.push({
pathname: `/${baseEndpoint}/query`,
search: `?description=${e.target[0].value}`,
})
}
一切看起来都很好,除非用户在 handleSubmit
将要重定向的页面中,即在 /${baseEndpoint}/query
。
如果用户在此页面中,历史将转到 /${baseEndpoint}/query?description=${e.target[0].value}
并自动重新呈现到 /${baseEndpoint}/query?
.
我也尝试过使用 history.replace
,但没有用。
const handleSubmit = (e) => {
let baseEndpoint = e.target[1].value === "Ações" ? "actions" : "quotes"
let url = `/${baseEndpoint}/query`
if(history.location.pathname === url) {
history.replace({
pathname: url,
search: `?description=${e.target[0].value}`,
})
return
}
history.push({
pathname: url,
search: `?description=${e.target[0].value}`,
})
}
是什么导致了这种行为?我做错了什么?
非常感谢!
(编辑)我的 Switch
和 Route
:
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
class Wrapper extends Component {
render() {
return (
<>
<Container className="main">
<MetaData />
<Navbar />
<this.props.component {...this.props} />
<br />
<br />
<Footer />
</Container>
</>
)
}
}
export default function App() {
return (
<Router>
<Switch>
<Route exact path="/"
render={props => (
<Wrapper {...props} component={Home} />
)}
/>
<Route
exact path="/actions"
key="action-home"
render={props => (
<Wrapper
{...props}
image={bozoAction}
baseEndpoint="actions"
component={EntityHome}
/>
)}
/>
<Route
path="/actions/query"
key="action-query"
render={props => (
<Wrapper
{...props}
image={bozoAction}
baseEndpoint="actions"
component={EntityQuery}
/>
)}
/>
<Route
path="/actions/:id(\d+)"
key="action-entity"
render={props => (
<Wrapper
{...props}
image={bozoAction}
baseEndpoint="actions"
component={Entity}
/>
)}
/>
<Route
exact path="/quotes"
key="quote-home"
render={props => (
<Wrapper
{...props}
image={bozoQuote}
baseEndpoint="quotes"
component={EntityHome}
/>
)}
/>
<Route
path="/quotes/query"
key="quote-query"
render={props => (
<Wrapper
{...props}
image={bozoQuote}
baseEndpoint="quotes"
component={EntityQuery}
/>
)}
/>
<Route
path="/quotes/:id(\d+)"
key="quote-entity"
render={props => (
<Wrapper
{...props}
image={bozoQuote}
baseEndpoint="quotes"
component={Entity}
/>
)}
/>
...
</Switch>
</Router>
)
}
沙盒:https://codesandbox.io/s/0y8cm
出于某种原因,沙箱没有重定向并忽略搜索参数,但我们可以通过执行以下操作来评估错误:使用导航栏搜索其中一个实体。检查表单(单击“Mais filtros”)并查看输入中提供的查询参数。在导航栏中再次搜索同一实体。检查表单,看不到初始值。
最佳答案
导致该行为的原因是表单提交事件,它刷新页面导致查询参数丢失,解决方法是提交表单时使用 e.preventDefault()
:
const handleSubmit = (e) => {
e.preventDefault(); // prevent the page refresh
let baseEndpoint = e.target[1].value === "Ações" ? "actions" : "quotes";
history.push({
pathname: `/${baseEndpoint}/query`,
search: `?description=${e.target[0].value}`
});
};
如果您绝对需要刷新页面,您可以添加 history.go()
,但我不建议这样做,目的是让子组件知道 search
已经改变了,
EntityQuery
和 QueryForm
的设置方式使得子组件无法知道是否有更改,因此您需要修复它,
你不应该在构造函数中设置 props 的初始状态值,因为它是 anti-pattern ,相反,具有初始值 empty
并使用生命周期方法更新它们( componentDidMount
和 componentDidUpdate
)
实体查询
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: true,
hasMore: false,
searchParams: {
page: 1,
tags: "",
description: ""
},
entities: []
}
}
updateStateValues = () => {
const _initialTag = this.props.location.search.includes("tags")
? this.props.location.search.split("?tags=")[1]
: "";
const _initialText = this.props.location.search.includes("description")
? this.props.location.search.split("?description=")[1]
: "";
this.setState({
searchParams: {
page: 1,
tags: _initialTag,
description: _initialText
}
})
}
componentDidMount() {
this.updateStateValues()
}
componentDidUpdate(prevProps) {
// add checks for other potential props that you need to update if they change
if (prevProps.location.search.split("?description=")[1] !== this.props.location.search.split("?description=")[1])
this.updateStateValues()
}
并将值从 state
传递给 child :
<QueryForm
baseEndpoint={this.props.baseEndpoint}
tagsInitialValues={this.state.searchParams.tags}
textInitialValue={this.state.searchParams.description}
setSearchParams={this.setSearchParams}
/>
编辑:
根据 OP 的评论和更新后的 SandBox,还有另一个关于 Formik
的问题,当 props
更改时,initialValues
不会更新,见:https://github.com/formium/formik/issues/811
建议的添加enableReinitialize
的解决方案不起作用,因此,要强制组件更新,您可以使用一个 key
,它会在 url 更改时更改,在在这种情况下,使用 this.props.textInitialValue
:
查询表单:
<Formik
key={this.props.textInitialValue}
...
关于reactjs - 如果用户已经在重定向页面上,history.push 会进行额外的重定向,并忽略搜索参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66726644/