React Doesn't Reload Component Data on Route Param Change or Query Change

React doesn't reload component data on route param change or query change

Along with componentDidMount, You also need to implement the componentWillReceiveProps or use getDerivedStateFromProps(from v16.3.0 onwards) in Products page since the same component is re-rendered with updated params and not re-mounted when you change the route params, this is because params are passed as props to the component and on props change, React components re-render and not re-mounted.

EDIT: from v16.3.0 use getDerivedStateFromProps to set/update state based on props(no need to specify it in two different lifecyle methods)

static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.match.params.product !== prevState.currentProductId){
const currentProductId = nextProps.match.params.product
const result = productlist.products.filter(obj => {

return obj.id === currentProductId;

})
return {

product: result[0],
currentId: currentProductId,
result

}
}
return null;
}

Prior v16.3.0, you would use componentWillReceiveProps

componentWillReceiveProps(nextProps) {
if (nextProps.match.params.product !== this.props.match.params.product) {
const currentProductId = nextProps.match.params.product
const result = productlist.products.filter(obj => {

return obj.id === currentProductId;

})
this.setState({

product: result[0],
currentId: currentProductId,
result

})
}
}

Working codesandbox

React Router does not update component if url parameter changes

When a URL's path changes, the current Component is unmounted and the new component pointed by the new URL is mounted. However, when a URL's param changes, since the old and new URL path points to the same component, no unmount-remount takes place; only the already mounted component receives new props. One can make use of these new props to fetch new data and render updated UI.

Suppose your param id is parameter.

  1. With hooks:

    useEffect(() => {
    // ... write code to get new data using new prop, also update your state
    }, [props.match.params.parameter]);
  2. With class components:

    componentDidUpdate(prevProps){
    if(this.props.match.params.parameter!== prevProps.match.params.parameter){
    // ... write code to get new data using new prop, also update your state
    }
    }
  3. Use KEY:

    Another approach could be to use the unique key prop. Passing a new key will force a
    component to remount.

    <Route path="/teams/:parameter" render={(props) => (
    <Team key={props.match.params.parameter} {...props} />
    )} />

Why React-router doesn't re-render the page and doesn't update the data when the url changes?

// Details.jsx description page 
<div className="description">
<p>BLa bla bla</p>
<Link to={`/${eleId}`}>Related</Link>
<div>

If Details component is linking to itself, i.e. the route rendering it, this means the route path is already matched and rendering Details. Details may need to "listen" for changes on the eleId route match param. Use the useParams React hook to access the eleId param and an useEffect hook with eleId as a dependency to run any side-effect necessary when the param updates.

Example:

import { useParams } from 'react-router-dom';

...

const Details = () => {

const { eleId } = useParams();
const [data] = useData(`alpha/${eleId}`);

...

useEffect(() => {
// Business logic to run when eleId updates
}, [eleId]);

...

For the useData hook, move the url declaration into the useEffect hook and add the param argument as a dependency for the effect. When the param changes this will retrigger the useEffect and refetch data.

const useData = (param = 'all') => {
const [data, setData] = useState([]);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
const url = 'https://restcountries.com/v2/' + param;

const fetchAPI = async () => {
setIsLoading(true);
try {
const response = await fetch(url);
const json = await response.json();
setData(json);
setError(false);
} catch(err) {
setError(err.message);
setData(null);
console.log(err);
}
setIsLoading(false);
};
fetchAPI();
}, [param]);

return [data, error, isLoading];
}

Component does not remount when route parameters change

If the link is directing to the same route with just a different param, it's not remounting, but instead receiving new props. So, you could use the componentWillReceiveProps(newProps) function and look for newProps.params.projectId.

If you're trying to load data, I would recommend fetching the data on before the router handles the match using static methods on the component. Check out this example. React Router Mega Demo. That way, the component would load the data and automatically update when the route params change without needing to rely on componentWillReceiveProps.

Component won't reload with new data when route parameters change

I think you're pretty close, but a mixture of misunderstanding lifecycle methods and when/how they are called is leading to some issues.

You probably should be using componentDidUpdate. I would also avoid storing the prop in state as they will then need to be kept in sync.

componentDidUpdate(prevProps) {
if (prevProps.match.params.id !== this.props.match.params.id) {
this.setState({ user: null });
fetchUserData(this.props.match.params.id)
.then((user) => {
this.setState({ user: user });
})
}
}

Also, don't manually trigger the lifecycle methods (as mentioned in the comments)

Query param not working on refresh or manual load

that's a normal behavior because your page is statically optimized

During prerendering, the router's query object will be empty since we do not have query information to provide during this phase. After hydration, Next.js will trigger an update to your application to provide the route parameters in the query object.

To be able to distinguish if the query is fully updated and ready for use, you can leverage the isReady field on next/router.

You have to use router.isReady in a useEffect, something like the code below:

const router = useRouter();
useEffect(()=>{
if(!router.isReady) return;

// codes using router.query

}, [router.isReady]);

React router: component not updating on url search param change

As @forJ correctly pointed out, the main idea is to make the component re render once the URL parameters change. I achieved it like so:

render() {
return (
<Switch>
<Route path="/hello" render={() => (<Hello key={this.props.location.key}/>)}></Route>
<Route path="/" component={Home}></Route>
</Switch>
);
}

this.props.location.key changes every time the URL changes (also if the query params change). So if you pass it as props to the component, then the component re renders on URL param changes, even though the base URL (the URL without the URL params) hasn't changed.

I also had to use the withRouter higher order component to make it work.

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Hello));


Related Topics



Leave a reply



Submit