Reputation: 4843
I expect that console.log('Refresh')
runs every time the route changes (switching from Component1 to Component2). But it's only triggering on first render. Why?
index.js
:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'));
App.js
:
import React, { useEffect } from 'react';
import { Switch, Route } from 'react-router-dom';
import Nav from './Nav';
import Component1 from './Component1';
import Component2 from './Component2';
const App = () => {
useEffect( () => console.log('Refresh'));
return (
[<Switch>
<Route component = {Nav}/>
</Switch>,
<Switch>
<Route exact path = '/component1' component = {Component1}/>
<Route exact path = '/component2' component = {Component2}/>
</Switch>]
);
}
export default App;
Nav.js
:
import React from 'react';
import { Link } from 'react-router-dom';
const Nav = () => {
return (
<div>
<Link to = '/component1'>Component 1</Link>
<Link to = '/component2'>Component 2</Link>
</div>
);
}
export default Nav;
Component1.js
:
import React from 'react';
const Component1 = () => {
return (
<div>
<p>Hi</p>
</div>
);
}
export default Component1;
Component2.js
:
import React from 'react';
const Component2 = () => {
return (
<div>
<p>Bye</p>
</div>
);
}
export default Component2;
Upvotes: 31
Views: 43832
Reputation: 1
if your are working with an identify :id
in your route like in
import react from 'react';
import { Route,Routes } from 'react-router-dom';
import Properties from './pages/properties';
function App() {
return (
<div>
<Routes>
<Route path="/" element={<Home/>} >
<Route path="properties/:id" element={<Properties/>}/>
</Route>
</Routes>
</div>
);
}
and you want the properties component to re-render
based on the identify :id
you can simply write this way in the properties component
import React,{useEffect} from "react";
import { useParams} from "react-router-dom";
export default Properties(){
useEffect(()=>{
return (){...}
},[useParams.id])
return <div> .....</div>
}
it will always re-render
the properties component for every change in the search parameter :id
Upvotes: 0
Reputation: 1978
Using Hooks:
use useLocation
and useLayoutEffect
get more efficiency:
import { useLocation } from "react-router-dom";
//...
const location = useLocation();
//...
useLayoutEffect(() => {
console.log("location",location)
}, [location])
Upvotes: 7
Reputation: 48085
Use the 2nd argument to useEffect to conditionally apply effect. For example via react-router-dom, you get some properties
const { schoolId, classId } = props
useEffect(() => {
// fetch something here
}, [schoolId, classId)
Here [schoolId, classId
acts as the unique identifier for useEffect to trigger.
Upvotes: 7
Reputation: 251
use the key attribute so everytime we render new component (different key)
<Route path='/mypath/:username' exact render= {routeProps =><MyCompo {...routeProps} key={document.location.href} />} />
Upvotes: 19
Reputation: 12691
The useEffect
is not triggered because the App
component is not re-rendered, nothing changed in that component (no state or props update).
If you want the App
component to re-render when the route change, you can use the withRouter
HOC to inject route props, like this :
import { Switch, Route, withRouter } from 'react-router-dom';
const App = () => {
useEffect( () => console.log('Refresh'));
return (...);
}
export default withRouter(App);
Example : https://codesandbox.io/s/youthful-pare-n8p1y
Upvotes: 25