React Route doesn't redirect - reactjs

I'm creating a blog, using React.
I uploaded some parts: https://codesandbox.io/s/youthful-bush-z3cce
There is one note on the main page and a list of other notes. When I click on some link of these notes, it opens and I can see another post. But if I try to click again on another post, it doesn't reload, though it changes the url.

It's because you have the same component rendering your posts. Your componentDidMount runs only once and it is responsible for calling your api. You need to get the api logic in a different function and call it again in componentDidUpdate.
I have done it in a codesanbox repo - https://codesandbox.io/s/musing-grass-sxokl
componentDidMount() {
if (!this.props.match) {
return;
} else {
this.callApi();
}
}
componentDidUpdate() {
this.callApi();
}
callApi = () => {
client
.getEntries({
content_type: "blogPost",
"fields.slug": this.props.match.params.slug
})
.then(response => {
console.log(response);
this.setState(
{
content: response.items[0].fields.content,
title: response.items[0].fields.title,
date: response.items[0].fields.date,
country: response.items[0].fields.country
},
() => console.log(this.state)
);
});
};
Hope this helps you.

Related

How can I optimize my code to stop sending GET requests constantly?

I am using the Yelp Fusion API to get a list of restaurants from Yelp. However, I am always constantly sending a GET request and I am not sure what is going on or how to fix it. I have tried React.memo and useCallback. I think the problem lies within how I am making the call rather than my component rerendering.
Here is where I send a GET request
// Function for accessing Yelp Fusion API
const yelpFusionSearch = async () => {
try {
const response = await yelp.get('/businesses/search', {
params: {
term: food,
location: location
}
})
// Saving our results, getting first 5 restaurants,
// and turning off our loading screen
setYelpResults({businesses: response.data.businesses.splice(0, 5)});
setEnableLoading(1);
}
catch (error) {
setEnableLoading(2);
}
};
This is where I use axios.
// Our Yelp Fusion code that sends a GET request
export default axios.create({
baseURL: `${'https://cors-anywhere.herokuapp.com/'}https://api.yelp.com/v3`,
headers: {
Authorization: `Bearer ${KEY}`
},
})
You are probably calling that function within your functional component and that function sets a state of that component, so it re-renders. Then the function is executed again, sets state, re-renders and so on...
What you need to do is to wrap that API call inside a:
useEffect(() => {}, [])
Since you probably want to call it one time. See useEffect doc here
You can do 2 things either use a button to get the list of restaurants because you are firing your function again and again.
const yelpFusionSearch = async () => {
try {
const response = await yelp.get('/businesses/search', {
params: {
term: food,
location: location
}
})
Use a button instead maybe so once that button is clicked function is fired.
<button onClick={yelpFusionSearch} />Load More Restaurants </button>
Use your fuction inside useEffect method which will load 5 restaurants once the page renders
useEffect(() => {
const yelpFusionSearch = async () => {
try {
const response = await yelp.get('/businesses/search', {
params: {
term: food,
location: location
}
})
}, [])

Delay a push to a page on success

I am currently working on pushing to a log in page on the confirmation of a user via email. Problem is, I would like to first re-direct the user confirming to a page thanking them for registering and a few seconds later push to the log in page. What's the best way of approaching this?
I have a push to the log in page that is happening right away, would like to delay it a few seconds.
confirmSuccess = () => {
this.setState(() => ({ success: true }));
this.props.history.push("/login", { fromRegistration: true });
};
Currently as soon as the user clicks on "confirm account" it pushes them straight the log in page, would like to have it delayed so the "thank you for registering" page can appear first.
You can create a new component like this
import React from "react"
import { withRouter } from "react-router-dom"
class ThankYouComponent extends React.Component {
componentDidMount() {
setTimeout(() => {this.props.history.push("/login")}, 5000) // redirect in 5 secs
}
render() {
return(
<h1>Thank You</h1>
)
}
}
export default withRouter(ThankYouComponent)
and in your confirmSuccess function redirect to ThankYouComponent page instead:
confirmSuccess = () => {
this.setState(() => ({ success: true }));
this.props.history.push("/thankYouPage", { fromRegistration: true });
};
And of course don't forget to add ThankYouComponent to Routes

Possible reason for unwanted page refresh in componentWillMount

After Login I want to show a license agreement page.
To show the license I used this code
index.js
componentWillMount(){
this.props.actions.user.LicenseAgreement();
}
action.js
export const LicenseAgreement = () => {
return(dispatch) =>{
authService.LicenseAgreement()
.then((response) =>{
window.location.href="/";
dispatch({type: LICENSE_AGREE, payload:response});
})
.catch((error)=>{
notification.error({
message: 'User',
description: error.message,
})
})
}
}
reducer.js
case LICENSE_AGREE: {
return{...state, agreement: action.payload.data.text}
}
The problem is that the page refreshes before clicking Agree button .
But when I commented componentWillMount() there was no refreshing.
So how could I stop refreshing of this page?
Use componentDidMount life cycle and remove window.location.href. Also to avoid refreshing, you can user Router

using componentWillUnmount in context of next js

I'm trying to run a method on componentWillUnmount(i'm using the next js framework).The issue is that the componentWillUnmount method does not fire. However componentDidMount is working fine.
class TeamMember extends Component {
constructor(props)
{
super(props);
this.state = {
teamMember: this.props.teamMember,
startDate: null,
}
}
static async getInitialProps ( context ) {
const { slug } = context.query;
const res = await fetch(``);
const teamMember = await res.json();
return {
teamMember:teamMember
}
}
async componentDidMount()
{
this.setState({
startDate: Date.now()
})
Tracker.pushObjectToStorage('profilesViewed',{
title:this.state.teamMember[0].title.rendered,
id:this.state.teamMember[0].id
})
}
async componentWillUnmount(props)
{
alert("ddffff");
console.log("ddsds");
}
}
this is my code for the page. when you leave the page I want the componentWillUnmount to fire. i've put an alert there for test purposes.
This is expected and intended behavior of Nextjs routing. For more information, you can check this issue: https://github.com/zeit/next.js/issues/2819.
When you go to another page, no unmounting of components occurs, but instead, a whole new page is rendered.
This is the same behaviour as if you were refreshing (or landing for the first time) on a page. A React component will not unmount when you hit F5 on a page, because it is not unmounting, the page is simply refreshing.

API call in React

I'm trying myself in react and trying to make a simple application, which will display articles from the Hacker News. I have already made the first call to their API
componentDidMount() {
fetch('https://hacker-news.firebaseio.com/v0/jobstories.json?print=pretty')
.then(res => res.json())
.then(articles => {
this.setState({articles})
})
}
As the response, it returns an array of the articles IDs. To get detailed information for every single article I need to iterate the array I get and to make a second request for every article ID which has to look like
fetch(`https://hacker-news.firebaseio.com/v0/item/{id_from_the_array}`)
And I faced the problem because I have no idea how to implement it in a correct way.. Could someone please advice me?
this will help you
import React from "react";
import { render } from "react-dom";
import Hello from "./Hello";
class App extends React.Component {
state = {
articles: []
};
componentDidMount() {
fetch("https://hacker-news.firebaseio.com/v0/jobstories.json?print=pretty")
.then(res => res.json())
.then(articles => {
articles.map(item => {
fetch(`https://hacker-news.firebaseio.com/v0/item/${item}.json?print=pretty`)
.then(res => res.json())
.then(detailArticles => {
const articles = this.state.articles.concat(detailArticles);
this.setState({ articles });
});
});
});
}
render() {
return <p>{JSON.stringify(this.state.articles) }</p>;
}
}
render(<App />, document.getElementById("root"));
codesandbox
One way you can do is like using pagenation or infinite scroll so you can show some 10 or 15 news on the screen and load the next set of data on click of a button. Else you can show only id's on screen and fetch the data on click of a button.

Resources