React Axios not rendering after setState - reactjs

I've got troubles with my Login component, I'm using the cointainer pattern, so i've got a component Login which manage the api call and a DumbLogin managing the input and warn the user about the response from my server.
I'm using Axios to do the api call, which use promises to do that, I'm also using arrow function to avoid troubles wiht the this, well that's what i was thinking...
Because in the end I have
TypeError: _this.setState is not a function
I tried to use a variable self to resolve that but that result in the same error.
How Am I suppose to do?
axios(all)
.then((response) => {
console.log(response);
if (response.status === 200){
this.setState({
...this.state,
spin: false,
});
let data = response.data;
this.props.connect(data.username, data.email, data.token, data.partners);
this.props.router.push('panel');
}
}).catch((error) => {
console.log(error.response);
this.setState({
spin: false,
errorLogin: 'Username or password wrong',
});
});
(spin is a boolean to inform DumbLogin that it should or not display a spinner while waiting for the response from my server)

it's because the this inside of the anonymous function inside of the then is not the this of the React component.
you need to bind the correct this(Reac Component's this) for the function which does the ajax call.
eg. if the function is:
fetchData(){
axios(all).then(...).catch(...)
}
you can bind it in the constructor:
constructor(){
this.fetchData = this.fetchData.bind(this)
}
HOWEVER!
This is not the recommended solution, you would usually dont want to do ajax call in the component... you may want redux, mobx or even redux-saga for this purpose

Related

React Native get dynamic data

there is a data which is changing every second in my api and i should get it dynamically to react native screen and im using setInterval
I writed a function which is send request and get data every second and i should refresh this function and i did use setInterval but im not sure about that is this healthy? also i could not solve this because i got an error that :
Possible Unhandled Promise Rejection (id: 7):
TypeError: _this2.setState is not a function. (In '_this2.setState({
kalanzaman: res.data
})', '_this2.setState' is undefined)
My func and how am i calling it :
dynamically() {
// console.log("bom")
axios.get(`http://localhost:5000/kalanzaman`)
.then(res => {
this.setState({ kalanzaman: res.data })
})
}
.
setInterval(this.dynamically, 1000)
Which way should i use for get dynamic data to react native from my api?
Instead of Http request, you can use Websocket.
It is a two-way interactive communication session between the user's browser and a server.
for example: have a look at Socket.IO
Maybe it would be better if you write it like this:
setInterval(() => {
dynamically() {
// console.log("bom")
axios.get(`http://localhost:5000/kalanzaman`)
.then(res => {
this.setState({ kalanzaman: res.data })
}).catch((error) => {
alert('Something Error')
})
}
}, 100);
You must cath() for catching the error, and put it on componentDidMount

How to use Axios to do a 2nd API get request call after componentDidMount, once the user interacts with your App?

I'm using Axios to do make an API call a (get request) inside the life cycle method componentDidMount.
It's working fine, I'm getting my result and saving the data using setState.
componentDidMount(){
axios.get("https://myAPI/v1/myAPI-Endpoint?myAPI-Key=12345678910abcdef")
.catch(error => console.log('Error', error))
.then(
(response) => {
let data = response.data;
this.setState({
myFetchedData: data
});
},
)
}
Then I use the data fetched to populate an autocomplete input, and once the user selects a value, I want to do another API call with the selected value
The question:
Where should I do that 2nd API call now, I assume that I cannot do it in componentDidMount since the component is already mounted?
So what is the best practice here? Where should I do an API call that is triggered by a user action?
Your autocomplete component is likely to have some sort of event that fires when a selection was made (something like 'onChange', 'onSelect', etc, this depends on the component).
You could then do something like this (in your render function):
<AutoComplete
onSelect={this.handleAutoCompleteSelect}
…
/>
and then, inside the component class:
…
handleAutoCompleteSelect (value) {
axios.get(apiEndpont, { value }) // Exact request depends on your api implementation
.catch(…)
.then(function (res) {
// Process request result here
})
}

How to set state the data in componentDidMount method from the epic redux-observable

I am new to redux-observable. I have an epic function which request an api call and emmit a new success action. What is the clean way to get the data in my react view? In my componentDidmount method I call the getUsers redux action. I wanted to set the state in componentDidmount but It will run only once and will not wait the promise epic.
const getUsersEpic = action$ =>
action$.ofType(GET_USERS)
.mergeMap( action =>
Observable.fromPromise(
axios({
method: 'get',
url: API_USERS,
headers : getHeaders().toObject()
})
)
)
.flatMap((response) => {
if(response.status == 200) {
return [{
type: GET_USERS_SUCCESS,
data: response.data,
status: response.status
}]
}
else {
return [{
type: GET_USERS_ERROR,
message: 'error',
status: response.status
}]
}
})
.catch( error => {
// console.log('error', error)
return setResponseError(error, GET_USERS_ERROR);
});
You dispatch an action in componentDidMount() that is intercepted by redux-observable and used to make ajax call. As a result, you get GET_USERS_SUCCESS or GET_USERS_ERROR action dispatched to redux at some point in the future. Generally, there is no way to await these actions in components. And I think it's a good limitation because this restricts async handling in the component which can in many ways introduce bugs.
What you need to do is set default state in reducer which is later updated by request response and pass it down as a props to your component.
Also, check out this answer by one of the redux-observable authors.
By the way is there any reason why you Axios instead AjaxObservable

How to Set the response to a state by using this.setState inside a componentDidMount() method

From my react application I made an Ajax request to the spring Mvc controller, got a Jason response from the requested spring controller.
Now am trying to set this response inside my componentDidMont () to a state defined inside the constructor using this.setState method using react js.
When I tried to set the state using this.setState method I get Type Error:
Cannot read property 'set State' of undefined error
Please do help me fix this error.
Course.js
import React from "react";
import Article from "../components/Article";
import axios from 'axios';
export default class Courses extends React.Component {
constructor() {
super();
this.state={items:[]};
}
componentDidMount() {
console.log("hello");
axios.get('http://localhost:8080/ulearn/rest/course/getAll').then(function (response) {
this.setState({items: response});
console.log(response);
}).catch(function (error) {
console.log(error);
});
}
Render method
render() {
return (
<div>
<div>Response - {this.state.items}</div>;
</div>
);
} }
Below is the error message:
In Javascript, defining an anonymous function does not automatically inherit the this context from the upper scope. So when you define an anonymous function callback for your ajax request, this becomes undefined inside it. Since you are already using ES6 features (like import and class) you can also use arrow functions with => to overcome the issue. They behave like normal functions, but do not create a new this context. So you can simply do this in your componentDidMount:
axios.get('http://localhost:8080/ulearn/rest/course/getAll')
.then((response) => {
this.setState({items: response});
console.log(response);
}).catch((error) => {
console.log(error);
});
As per the error in your comment, as the response above mine beat me to answering your question :) -
You are trying to print out the entire object, try printing out each item individually or adding .toString() behind this.state.items in your render method. The same thing happens when you try to print new Date() for example, it won't let you print out the entire object, but it will let you print a string representation of the object, so new Date().toString() would work for example.

How do I make an HTTP request in react-redux?

I am just getting started with react and I'm a bit lost. I'm trying to make a login page and make a http post request. Right now I'm just trying to get any type of HTTP request working, so I'm using request bin and I found this basic action in the docs for an npm package (https://www.npmjs.com/package/redux-react-fetch):
export function updateTicket(ticketId, type, value){
return {
type: 'updateArticle',
url: `http://requestb.in/1l9aqbo1`,
body: {
article_id: ticketId,
title: 'New Title'
},
then: 'updateTicketFinished'
}
}
So, after writing an action, what do I do? How do I actually get my app to call on and use that action? The docs for the npm package mention something about setting a state in my store, is that something I need to set up first?
You can try any of the following. I have used both fetch and axios they work amazingly well. Yet to try superagent.
For making requests you can either use fetch with
fetch-polyfill for compatibility across all browsers (link)
Axios library. (link)
Superagent with promises.(link)
If you use fetch you would need to use polyfill since it is not supported in IE and safari yet. But with polyfill it works pretty well. You can check out the links for how you can use them.
So what you would doing is in your action creator you can call an API using any of the above.
FETCH
function fetchData(){
const url = '//you url'
fetch(url)
.then((response) => {//next actions})
.catch((error) => {//throw error})
}
AXIOS
axios.get('//url')
.then(function (response) {
//dispatch action
})
.catch(function (error) {
// throw error
});
So that was for the API call, now coming to the state. In redux there is one state which handles your app. I would suggest you should go through redux basics which you can find here . So once your api call succeeds you need to update your state with the data.
Action to fetch data
function fetchData(){
return(dispatch,getState) =>{ //using redux-thunk here... do check it out
const url = '//you url'
fetch(url)
.then (response ) => {dispatch(receiveData(response.data)} //data being your api response object/array
.catch( error) => {//throw error}
}
}
Action to update state
function receiveData(data) {
return{
type: 'RECEIVE_DATA',
data
}
}
Reducer
function app(state = {},action) {
switch(action.types){
case 'RECEIVE_DATA':
Object.assign({},...state,{
action.data
}
})
default:
return state
}
}

Resources