reactjs - 如果用户已经在重定向页面上,history.push 正在执行额外的重定向,并忽略搜索参数
问题描述
我有一个简单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
s:
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
设置方式使子组件无法知道是否有更改,因此您需要修复它,
您不应该从构造函数中的道具设置初始状态值,因为它是反模式的,而是具有初始值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
时initialValues
不更新的props
问题,请参阅:https ://github.com/formium/formik/issues/811
建议的添加解决方案enableReinitialize
不起作用,因此,要强制组件更新,您可以使用key
在 url 更改时更改的 a,在这种情况下,请使用this.props.textInitialValue
:
查询表格:
<Formik
key={this.props.textInitialValue}
...
推荐阅读
- javascript - 检查对象属性的值和检查属性是否在对象中的区别
- cmake - find_library 如何处理版本号?
- javascript - Event.target.value 返回空字符串或空白
- ruby-on-rails - 在测试环境中禁用伪造保护时,测试如何抛出 InvalidAuthenticityToken?
- angular - Angular 中的 @Input 和 @HostBinding 装饰器有什么区别?
- python - Django:唯一约束失败:user.username
- bitbucket-pipelines - 为什么类星体“构建”不是一个已知命令?
- react-native - 在 Arduino 和 React Native 应用程序之间设置加密密钥
- python - 使用浮点列表进行循环
- sql - 在 Google Big Query 中将两个数组连接在一起