Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

this.props.history.push not re-rendering react component

Tags:

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;
like image 833
shotofcode Avatar asked Jul 19 '18 07:07

shotofcode


People also ask

Does history Push re render?

history. push is updating url but not re rendering : r/reactjs.

How does history Push work in react?

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.

How is useHistory used in the functional component of react?

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!


2 Answers

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)

like image 171
Darkilen Avatar answered Oct 20 '22 06:10

Darkilen


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 componentDidMountand componentDidUpdate.

like image 31
Mauricio Avendaño Avatar answered Oct 20 '22 04:10

Mauricio Avendaño