Issue
I'm building a web app using React Redux and React Router. In my app I have a component called Listings, where the user can use a search bar to filter for certain types of listings. Everything works perfectly as long as the user is not on the listings page. But when the user tries to use the search bar from the listings page as opposed to the home page, the component doesn't re-render. I kinda get why this is happening as the DOM isn't changing, but have yet to figure out a workaround.
I also get this warning "react_devtools_backend.js:4026 Warning: Hash history cannot PUSH the same path; a new entry will not be added to the history stack"
Below is the relevant code in the search component
handleSubmit(e) {
e.preventDefault;
const searchUrl = new URLSearchParams(this.state).toString();
this.props.history.push({
pathname: `/listings/`,
key: Math.random(),
search: `${searchUrl}`
})
}
And here is some of the code in my Listings component
class Listings extends React.Component {
constructor(props) {
super(props);
this.state = {listings: props.listings};
}
componentDidMount() {
this.props.indexListings();
}
componentDidUpdate(prevProps) {
if (this.props.listings != prevProps.listings) {
if (this.props.history.location.search) {
const queryString = require('query-string');
const parsed = queryString.parse(this.props.location.search);
const listings = [...this.props.listings];
this.setState({listings: listings.filter(listing => listing.city.includes(parsed.city))});
} else {
const listings = [...this.props.listings];
this.setState({listings: listings});
}
}
}
Listing Container Code
import { connect } from "react-redux";
import { indexListings } from "../../actions/listing_actions";
import Listings from "./Listings";
const mapStateToProps = state => ({
listings: Object.values(state.entities.listings)
})
const mapDispatchToProps = dispatch => ({
// this gets all the listings from the backend
indexListings: () => dispatch(indexListings())
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(Listings);
as well as the code in my App component
const App = () => (
<Switch>
<AuthRoute path="/login" component={LoginFormContainer} />
<AuthRoute path="/signup" component={SignupFormContainer} />
<Route path = "/listings/" component={ListingsContainer}/>
<Route path = "/users/show/" component={UserContainer}/>
<Route path = "/listing/new/" exact component={NewListingContainer}/>
<Route path = "/listing/:id/" component={ShowListingContainer}/>
<Route path = "/" component={Splash} />
</Switch>
);
Any advice at all or constructive feedback would be well appreciated!
Solution
@Drew-Reese was correct that my ComponentDidUpdate logic was flawed and the issue is now resolved. I thought the issue was that no methods in the component were getting called the second time around but I was wrong. Upon using the search bar a second time (while already in the Listings Component), componentDidUpdate actually does get called but my conditional wasn't registering a change in props.histroy. I've since changed if (this.props.listings != prevProps.listings)
to if (this.props != prevProps)
at the top of componentDidUpdate! Thanks everyone for helping me solve this issue.
Answered By - Harry
Answer Checked By - - Gilberto Lyons (ReactFix Admin)