In my component I use this.props.history.push(pathname:.. search:..) to rerender the component and fetch new data form a third party service. When I first call the page it renders. But when I call history push inside the component the URL updates correctly BUT the component doesn't rerender. I read a lot but couldn't get it working. Any ideas?
I'm using react router v4
//index.js <Provider store={store}> <BrowserRouter> <Switch> <Route path="/login" component={Login}/> <Route path="/" component={Main}/> </Switch> </BrowserRouter> </Provider> //Main.js //PropsRoute is used to push props to logs component so I can use them when fetching new data const PropsRoute = ({ component: Component, ...rest }) => { return ( <Route {...rest} render={props => <Component {...props} />}/> ); }; class Main extends Component { render() { return ( <div className="app"> <NavigationBar/> <div className="app-body"> <SideBar/> <Switch> <PropsRoute path="/logs" component={Log}/> //this component is not rerendering <Route path="/reports" component={Reports}/> <Route path="/gen" component={Dashboard}/> <Redirect from="/" to="/gen"/> </Switch> </div> </div> ) } } export default Main; //inside 'Log' component I call import React, {Component} from 'react'; import {getSystemLogs} from "../api"; import {Link} from 'react-router-dom'; import _ from "lodash"; import queryString from 'query-string'; let _isMounted; class Log extends Component { constructor(props) { super(props); //check if query params are defined. If not re render component with query params let queryParams = queryString.parse(props.location.search); if (!(queryParams.page && queryParams.type && queryParams.pageSize && queryParams.application)) { this.props.history.push({ pathname: '/logs', search: `?page=1&pageSize=25&type=3&application=fdce4427fc9b49e0bbde1f9dc090cfb9` }); } this.state = { logs: {}, pageCount: 0, application: [ { name: 'internal', id: '...' } ], types: [ { name: 'Info', id: 3 } ], paginationPage: queryParams.page - 1, request: { page: queryParams.page === undefined ? 1 : queryParams.page, type: queryParams.type === undefined ? 3 : queryParams.type, pageSize: queryParams.pageSize === undefined ? 25 : queryParams.pageSize, application: queryParams.application === undefined ? 'fdce4427fc9b49e0bbde1f9dc090cfb9' : queryParams.application } }; this.onInputChange = this.onInputChange.bind(this); } componentDidMount() { _isMounted = true; this.getLogs(this.state.request); } componentWillUnmount() { _isMounted = false; } getLogs(request) { getSystemLogs(request) .then((response) => { if (_isMounted) { this.setState({ logs: response.data.Data, pageCount: (response.data.TotalCount / this.state.request.pageSize) }); } }); } applyFilter = () => { //reset page to 1 when filter changes console.log('apply filter'); this.setState({ request: { ...this.state.request, page: 1 } }, () => { this.props.history.push({ pathname: '/logs', search: `?page=${this.state.request.page}&pageSize=${this.state.request.pageSize}&type=${this.state.request.type}&application=${this.state.request.application}` }); }); }; onInputChange = () => (event) => { const {request} = this.state; //create copy of current object request[event.target.name] = event.target.value; //update object this.setState({request}); //set object to new object }; render() { let logs = _.map(this.state.logs, log => { return ( <div className="bg-white rounded shadow mb-2" key={log.id}> ... </div> ); }); return ( <main className="main"> ... </main> ); } } export default Log;
history. push is updating url but not re rendering : r/reactjs.
history. push() is another approach where we make use of the history props React Router provides while rendering a component. In other words, this works when the component is being rendered by React Router, bypassing the component as a Component prop to a Route.
All we need to do is to call the useHistory hook inside a functional component: import { useHistory } from 'react-router-dom'; const App = () => { const history = useHistory(); const redirect = () => { history. push('/login'); } return ( <div> <h1>Hi there!
Reactjs don't re-run the constructor
method when just props
or state
change, he call the constructor
when you first call your component.
You should use componentDidUpdate
and do your fetch if your nextProps.location.pathname
is different than your this.props.location.pathname
(react-router location)
I had this same issue with a functional component and I solved it using the hook useEffect with the props.location
as a dependency.
import React, { useEffect } from 'react'; const myComponent = () => { useEffect(() => { // fetch your data when the props.location changes }, [props.location]); }
This will call useEffect
every time that props.location
changes so you can fetch your data. It acts like a componentDidMount
and componentDidUpdate
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With