React Redux Router:同URL不同查询参数时组件不重渲染求助
问题修复方案
一、解决"Hash history cannot PUSH the same path"警告
修复搜索组件的handleSubmit方法
- 首先修正表单默认提交的错误:
e.preventDefault需要调用函数,改为e.preventDefault(),否则表单会触发页面刷新。 - 避免重复向历史栈添加相同路径:判断当前是否已在列表页,若是则用
replace更新URL参数,而非push;若不在则正常跳转。
修改后代码:
handleSubmit(e) { e.preventDefault(); // 修正:调用函数阻止默认提交 const searchUrl = new URLSearchParams(this.state).toString(); const currentPath = this.props.history.location.pathname; if (currentPath === '/listings/') { // 当前在列表页,用replace更新URL参数,不新增历史记录 this.props.history.replace({ pathname: '/listings/', search: searchUrl }); } else { // 不在列表页,跳转并添加历史记录 this.props.history.push({ pathname: '/listings/', search: searchUrl }); } }
二、解决Listings页面内搜索不重渲染的问题
修正Listings组件的componentDidUpdate逻辑
当前代码仅监听props.listings变化,但搜索时是URL参数(props.location.search)变化,props.listings可能未更新,因此需要同时监听location的变化。
修改后代码:
componentDidUpdate(prevProps) { // 监听房源数据变化 或者 URL搜索参数变化 const listingsChanged = this.props.listings !== prevProps.listings; const searchChanged = this.props.location.search !== prevProps.location.search; if (listingsChanged || searchChanged) { let filteredListings = [...this.props.listings]; if (this.props.location.search) { const queryString = require('query-string'); const parsed = queryString.parse(this.props.location.search); filteredListings = filteredListings.filter(listing => listing.city.includes(parsed.city)); } this.setState({ listings: filteredListings }); } }
可选优化:移除组件内的筛选结果状态
无需在组件state中存储筛选后的房源,直接在render阶段根据props计算,更符合React数据流:
render() { let filteredListings = [...this.props.listings]; if (this.props.location.search) { const queryString = require('query-string'); const parsed = queryString.parse(this.props.location.search); filteredListings = filteredListings.filter(listing => listing.city.includes(parsed.city)); } return ( // 使用filteredListings渲染列表内容 ); }
优化后可删除constructor中对listings状态的初始化,以及componentDidUpdate内的setState逻辑。
确保组件获取路由props
如果Listings容器组件未直接被Route渲染,需要用withRouter高阶组件包裹,确保能拿到location、history等路由相关props:
import { connect } from "react-redux"; import { withRouter } from "react-router-dom"; // 导入withRouter import { indexListings } from "../../actions/listing_actions"; import Listings from "./Listings"; const mapStateToProps = state => ({ listings: Object.values(state.entities.listings) }) const mapDispatchToProps = dispatch => ({ indexListings: () => dispatch(indexListings()) }) // 先用withRouter包裹,再执行connect export default withRouter(connect( mapStateToProps, mapDispatchToProps )(Listings));
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

