React componentDidMount not setting states before page loads - arrays

Working on a MERN application, I have a componentDidMount that uses axios to retrieve from the backend some Ids and retrieve product info(prods) from the ids. However the states in my application are still empty when the page is loaded initially, instead I'll have to make a change to state before the states are set.
I believe it might have something to do with having an array mapping in the componenDidMount, I could change the backend so in node. However i would like to see if anything could be done in the frontend first.
componentDidMount() {
axios
.get("/api/featureds")
.then(response => {
this.setState({
featureIds: response.data
});
response.data.map(({ prodId, _id }) =>
axios
.get("/api/prods/" + prodId)
.then(response => {
if (response.data == null) {
} else {
this.state.featureTempList.push(response.data);
}
})
.catch(error => {
console.log(error);
})
);
this.setState({
featureProds: this.state.featureTempList
});
})
.catch(error => {
console.log(error);
});
}

Why are you trying to set state like this?
this.state.featureTempList.push(response.data)
State should be set by this.setState().
So you can try doing this:
this.setState((oldState) => ({
featureTempList: oldState.featureTempList.push(response.data)
});
Just remember to set featureTempList to state when you initialize:
state = {
featureTempList: []
}

Related

How to set state of other component inside an axios get method in react?

I'm using class-based components in react. I have few components named as follows: Blogs, BlogsClient, BlogCard. When Blogs mounts I make a call to a function inside BlogClient named as getBlogContent to fetch me data using axios.
setBlogs = (blogs) => {
this.setState({ "blogs": blogs });
}
componentDidMount() {
getBlogContent(this.setBlogs);
}
where getBlogContent is:
let getBlogContent = (setBlogs) => {
store.set('loaded', false);
axios.get(ADMIN_URL + '/getAllBlogs')
.then(response => {
store.set('loaded', true);
setBlogs(response.data.Response);
})
.catch(error => {
store.set('loaded', true);
store.set('errorMessage', error);
})
}
I'm able to fetch data and update my state properly. But If there comes any error inside Blogs or BlogCard(which is called inside Blogs) it goes inside the catch of getBlogContent whereas it should be only responsible for catching Axios error. What am I missing here?
Ok, so it's hard to tell without knowing these errors..
But nonetheless, you should avoid setting the component's state outside that component. So, your code'd become:
componentDidMount() {
const blogContent = getBlogContent();
if (blogContent !== 'error'j this.setBlogs(blogContent);
}
let getBlogContent = () => {
store.set('loaded', false);
return axios.get(ADMIN_URL + '/getAllBlogs')
.then(response => {
store.set('loaded', true);
return response.data.Response;
})
.catch(error => {
store.set('loaded', true);
store.set('errorMessage', error);
return 'error';
})
}

Pagination in React-Redux

So I'm just trying to make a pagination component in react. Im currently using redux for my state management and using semantic-ui for the pagination component.
I have currently made a react component in my action.jsx file and have two other functions which one of them is for data fetching for my redux state and one other for the declaring the current active page value and set the new target url for data fetching.
export class Paginator extends React.Component {
state = {
page: [],
pages: []
}
handlePage(activePage) {
let pagenum = activePage;
let pagestring = pagenum.toString();
paginationUrl = '/api/v1/products/index/?page=' + pagestring; ----> Pass This Url
}
componentDidMount() {
axios.get("/api/v1/products/index", { withCredentials: true })
.then(response => {
this.setState({
page: response.data.page,
pages: response.data.pages
})
})
.catch(error => {
console.log("Check Login Error", error);
});
}
render() {
return(
<Pagination onPageChange={this.handlePage} size='mini' siblingRange="6"
defaultActivePage={this.state.page}
totalPages={this.state.pages}
/>
)
}
}
export function fetchProducts() {
return (dispatch) => {
dispatch(fetchProductsRequest())
axios
.get("To Here !")
.then(response => {
// response.data is the products
const products = response.data.products
dispatch(fetchProductsSuccess(products))
})
.catch(error => {
// error.message is the error message
dispatch(fetchProductsFailure(error.message))
})
}
}
The question is how am i able to pass the paginationUrl to the function below ? (Actually, there is no way i guess !).
Note: I am only able to use handlePage in the same component with the pagination component.
Waiting for suggestions, Thx in advance ;)
You could pass the URL to the fetchProducts function when dispatching actions on page changes.
handlePage(activePage) {
const url = `/api/v1/products/index/?page=${activePage}`
dispatch(fetchProducts(url))
}
And update the fetchProducts action creator to use the URL.
export function fetchProducts(url) {
return (dispatch) => {
dispatch(fetchProductsRequest())
axios
.get(url)
.then((response) => {
dispatch(fetchProductsSuccess(response.data.products))
})
.catch((error) => {
dispatch(fetchProductsFailure(error.message))
})
}
}
This is unrelated to the question but I would strongly recommend using React Query to simplify data fetching and synchronization.

How to send updated state in axios in React?

I am trying to send post request using axios in Reactjs.
I have two component a timer component and App component and in App component i am trying to submit a form and send an axios call when i fetch the time from Timer component and save itinto counter state
I have written a condition if counter is true then update my state and then further send the post request
Working Demo
here is a handle submit code:
const handleSubmit = e => {
console.log("handleSubmit");
e.preventDefault();
if (counter) {
console.log(counter);
const url = `url string`;
setState({
...state,
lastn: {
attestedTime: myDateFunc(),
time: counter
}
});
console.log(state);
axios
.post(url, state)
.then(response => {
console.log(response);
console.log(response.data);
})
.catch(error => {
console.log(error);
});
}
};
The problem is when counter is true its not update the state which causes error while send axios request.
I have consoled each and every thing but still it fails.
It seems there is lot of rendering.
If you are using class components, you can make the reuqest after the state has been set. Something like this:
this.setState({
...state,
lastn: {
attestedTime: myDateFunc(),
time: counter
}
}, () => {
axios
.post(url, state)
.then(response => {
console.log(response);
console.log(response.data);
})
.catch(error => {
console.log(error);
});
});
Since you did set the react-hooks tag, I guess that approach is not what you need. In your case, I suggest saving new state in some temporary variable and than passing that variable to axios. Like this:
const newState = {
...state,
lastn: {
attestedTime: myDateFunc(),
time: counter
}
};
setState(newState);
axios
.post(url, newState)
.then(response => {
console.log(response);
console.log(response.data);
})
.catch(error => {
console.log(error);
});
setState can be executed asynchronously by React, to optimize the rendering process. For cases like this one, it can also take a callback function that is guaranteed to be executed after updating the state.
For example:
this.setState({
name:'value'
},() => {
console.log(this.state.name);
});
in this case console.log will be executed after setting the name variable.
see the docs: https://reactjs.org/docs/react-component.html#setstate

React how can i replace the valeur of data

as you can see on , i have two way to get the data.
The first one is localy, use the getdata() to read from local file.
function getData() {
const data = testData.map(item => {
return {
...item
};
});
return data;
}
The second one is a distance.
componentDidMount() {
fetch('https://XXXXX')
.then(res => res.json())
.then((data) => {
this.setState({ todos: data })
console.log(this.state.todos)
})
}
both work, but somehow i can not bind the second one to my app.
i am newbie on react technologie.
I think you can't define 2 state obj.
you have to delete one of them

Cannot fetch api due to array react native

I bulid an api using laravel which can run in postman (http://lkcfesnotification.000webhostapp.com/api/notifications). The problem is when i fetch using an example from this (https://www.youtube.com/watch?v=IuYo009yc8w&t=430s) where there is a array in the api then i have to setstate the array which is working well but when i try using the below code it does not render due to it is not using array in the api for example the random user api have "results" :[item], and mine one is "data":[my item]
fetchData = async () => {
const response = await fetch("https://randomuser.me/api?results=500");
const json = await response.json();
this.setState({ data: json.results });
};
if i use this will work but i want to use below code due to some homework i am doing
type Props = {};
export default class IndexScreen extends Component<Props> {
...
this.state = {
data: [],
isFetching: false,
};
_load() {
let url = "http://lkcfesnotification.000webhostapp.com/api/notifications";
this.setState({isFetching: true});
fetch(url)
.then((response) => {
if(!response.ok) {
Alert.alert('Error', response.status.toString());
throw Error('Error ' + response.status);
}
return response.json()
})
.then((members) => {
this.setState({data});
this.setState({isFetching: false});
})
.catch((error) => {
console.log(error)
});
}
https://imgur.com/a/he5mNXv this is my render
the result i get the code i run is blank is loading
The fetch request is working but you are not saving the right data in the right state property.
The issues is located in the following part:
.then((members) => {
this.setState({data});
this.setState({isFetching: false});
})
You are assigning the response to a variable members but saving another variable data, which does not exist.
In addition, the response is an object with more information than just the data, so what you are looking for is just the data property of the response.
This should work:
.then(({ data }) => {
this.setState({data});
this.setState({isFetching: false});
})
Here we destructure the response into the variable { data }, solving your issue.
Based on the snippets you don't use the fetched data to set it to your state:
.then((members) => {
this.setState({data});
this.setState({isFetching: false});
})
membersis the result of your fetched json. So either rename members to data or use data: members. If the code should work like your first function it's probably data: members.result. You can also combine the two setState calls to one single call:
this.setState({
data: members.result,
isFetching: false,
});

Resources