I am searching a lot about this topic but can’t seem to find a answer that clarifies me.
I am trying to make my first react app. I have started with create react app to understand the basics and then moved my app to server side rendering. As I was developing I got in a question. How can I fetch some data from my API before the app gives a answer (server side) so I can put some stuff in there that I really need?
You could use an ajax request to pull the data from API and set that to the state variable of react. So that the state variable will be used during render. You could define a method for this and, you can call that method from componentDidMount() to set the values to the state variable.
var CommentBox = React.createClass({
getInitialState: function() {
return {data : []};
},
loadCommentsFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
handleCommentSubmit: function(comment){
var comments = this.state.data;
var newComments = comments.concat([comment]);
this.setState({data: newComments});
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: comment,
success: function(data) {
console.log(data);
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer(), this.props.pollInterval);
},
render: function() {
return (
<div className='commentBox'>
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
});
In the above code sample, I wrote a method loadCommentsFromServer() specifically to pull data from an API. And I call that from componentDidMount() and stored the output from API into state variable. And, I used the state variable during render.
Note: The above code sample may not work on its own. Since, it's dependencies are not resolved.
Related
I have a JSON response, one that I can't figure out. Here is my current response that I receive.
This is my ajax script:
<script>
$(document).on('click', '#pullDetails', function() {
$.ajax({
type:'POST',
url: '/carrier/claims/pullDetails',
data: {
num: $('input[name=proNumber]').val(),
_token: $('input[name=_token]').val()},
dataType: 'json',
success: function(data) {
if(data.details != undefined) {
console.log('success');
console.log(data.details.SearchResults[0].Shipment.Origin.Name); //result: ATLAS INTL
$('#carrierReturnData').html(data.details.SearchResults[0].Shipment.Origin.Name);
}else{
console.log('failed');
console.log(data);
console.log(data.details.SearchResults.SearchItem);
}
},
error: function(data) {
console.log('error');
console.log(data);
}
});
});
</script>
Now my question is how would I get the specific data from the line "SearchItem" (on the first line of the response json)?
At the moment I get the following: TypeError: data.details.SearchResults is undefined, but data.details is recognized as my console logs "success."
Do a JSON.parse of details and then try to log SearchResults
var results = JSON.parse(data.details);
console.log(results.SearchResults.SearchItem);
I am trying to create an app that counts likes for beer! This would updates the API the beers are stored on and in turn update the number of likes on the API and angularJS view using the PUT method. I am able to get the view to work correctly increasing every time the like is clicked. I am unsure why my PUT method continues to return a 404 and will not update the API. please see code below for my put method. I have also included my JS and HTML for this. I feel like I am close but cannot figure out how to get the "likes" to update on the API. Thank you in advance!! I think i am passing incorrect data to the PUT method.
HTML:
<div ng-app="beerApp" ng-controller="BeerController" class="jumbotron">
<div class="all-beer">
<div class="single-beer" ng-repeat="beer in allBeer">
<div>{{beer.name}}</div>
<div>{{beer.likes}}</div>
<button ng-click="decrease(beer)">X</button>
<button ng-click="increase(beer)">\3</button>
</div>
</div>
</div>
JS:
angular.module('beerApp', []).controller('BeerController', function($scope, $http) {
$scope.allBeer = [];
$scope.beerSum = function() {
$http({
method: 'GET',
url: /api/beers
}).
then( function(response) {
if(typeof response === 'object') {
var dataArr = response.data;
for (var i = 0; i < dataArr.length; i++) {
var beer = dataArr[i];
$scope.allBeer.push(beer);
}
} else {
return;
}
}, function(error) {
console.log('i am an error', error);
})
};
$scope.beerSum();
$scope.increase = function(beer){
var newLikes = beer.likes++;
$http({
method: 'PUT',
url: '/api/beer/',
data: JSON.stringify($scope.allBeer.likes),
}).then(function successCallback(response) {
console.log("Updated!");
}, function errorCallback(response) {
console.log("not updated")
});
};
First things first you are missing some syntax for the http api's. Secondly you are calling a property on an array that doesn't exist. Thirdly your api won't work because of the logic that you have. You have an array of beers and you want to increase the likes on a single beer. Create a method on the server that accepts a beer, the server will take that beer and increase it's likes by 1, then save to the database or whatever.
Depending on the server you are using you have two options.
You can define a command simply at /api/beers and configure the server to accept an object and use that objects id for the server update. If this is the case I recommend creating this endpoint, /api/beers/update and make it a POST, and pass it the object, then within this command do all your update logic.
Or for example the Microsoft Web Api the default put (update) endpoint looks like so, public void Update(int id, object data){} with a url of /api/beers/{id}. To use this method you need to change the code for the updateLikes method I wrote.
See Below:
$scope.updateLikes = function(beer, likeCount){
beer.likes+= likeCount;
$http({
method: 'PUT',
url: '/api/beer/' + beer.id,
data: JSON.stringify(beer),
}).then(function successCallback(response) {
console.log("Updated!");
//Trigger reload of data
$scope.beerSum();
}, function errorCallback(response) {
console.log("not updated")
});
};
Extra Help
If you are still having trouble and are working in a GitHub environment I would gladly help you with your code more directly. Other than that the answer I have posted answer's your question, and does so in what I believe to be good coding practices for AngularJS. With one minor exception there code be a changes to the line that reads, beer.likes += likeCount because this also updates the original beer object. I suppose that is preference, but please contact me if you need more help.
JS:
angular.module('beerApp', []).controller('BeerController', function($scope, $http) {
$scope.allBeer = [];
$scope.beerSum = function() {
$http({
method: 'GET',
url: '/api/beers' //<-- Added string opening and closing tags
}).
then( function(response) {
if(typeof response === 'object') {
var dataArr = response.data;
for (var i = 0; i < dataArr.length; i++) {
var beer = dataArr[i];
$scope.allBeer.push(beer);
}
} else {
return;
}
}, function(error) {
console.log('i am an error', error);
})
};
$scope.beerSum();
$scope.increase = function(beer){
var newLikes = beer.likes++;
//Your code
$http({
method: 'PUT',
url: '/api/beer/', //<-- closing
data: JSON.stringify($scope.allBeer.likes), //<-- Where does likes come from? $scope.allBeer is an array of beer but the array itself doesn't have a property called likes.
}).then(function successCallback(response) {
console.log("Updated!");
}, function errorCallback(response) {
console.log("not updated")
});
//End your code
//My Code
beer.likes+=1; //<-- My bad I fixed this.
$http({
method: 'PUT',
url: '/api/beer/', //<-- closing
data: JSON.stringify(beer), //<-- The object you passed into the function
}).then(function successCallback(response) {
console.log("Updated!");
}, function errorCallback(response) {
console.log("not updated")
});
//End my code
};
Possible problems
Your api doesn't work with put, in which case this question isn't the correct one.
Something else is internally wrong with your program, but from this point on I think you're looking at something wrong with your api, whatever that may be.
angular.module('beerApp', []).controller('BeerController', function($scope, $http) {
$scope.allBeer = [];
$scope.beerSum = function() {
$scope.allBeer.push({
"name": "Miller Lite",
"likes": 0
});
$http({
method: 'GET',
url: '/api/beers' //<-- Added string opening and closing tags
}).
then( function(response) {
if(typeof response === 'object') {
var dataArr = response.data;
for (var i = 0; i < dataArr.length; i++) {
var beer = dataArr[i];
$scope.allBeer.push(beer);
}
}
}, function(error) {
console.log('i am an error', error);
})
};
$scope.beerSum();
$scope.updateLikes = function(beer, likeCount){
beer.likes+= likeCount;
$http({
method: 'PUT',
url: '/api/beer/',
data: JSON.stringify(beer),
}).then(function successCallback(response) {
console.log("Updated!");
//Trigger reload of data
$scope.beerSum();
}, function errorCallback(response) {
console.log("not updated")
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-app="beerApp" ng-controller="BeerController" class="jumbotron">
<h1>Beers on Tap</h1>
<div class="all-beer">
<div class="single-beer" ng-repeat="beer in allBeer">
<div>{{beer.name}}</div>
<div>{{beer.likes}}</div>
<button ng-click="updateLikes(beer, -1)">Down Vote</button>
<button ng-click="updateLikes(beer, 1)">Up Vote</button>
</div>
</div>
</div>
</body>
</html>
I have an API I want to ensure that api has called mean get alert "api hit" else "api does not meet"
$http.post('v1/xyz/eeee res')
.success(function () {
////
})
Don't use the success method either way.Both methods have been deprecated.
The $http legacy promise methods success and error have been
deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.
Here is the shortcut method
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
Here is a longer GET method sample
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Official Documentation
See Priya this is how it happens
Controller Coding :-
angular.module('myApp', [])
.controller('myCtrl', function ($scope, $http) {
$scope.hello = {name: "Boaz"};
$scope.newName = "";
$scope.sendPost = function() {
var data = $.param({
json: JSON.stringify({
name: $scope.newName
})
});
$http.post("/echo/json/", data).success(function(data, status) {
$scope.hello = data;
}).error(function(data, status, headers, config) {
// this isn't happening:
$scope.hello=data;
console.log('this is nt happening '+data.status);
})
}
})
Html Coding :-
<div ng-controller="myCtrl">
{{hello}}
<form ng-submit="sendPost()">
<input ng-model="newName"/>
<button type="submit">Send</button>
</form>
</div>
Finally You can see the Error result in My Fiddle :-
http://jsfiddle.net/bkUEu/2589/
with error status also
Hint :- Just replace post end-Point with : /echo/ Instead /echo/json/
Let Me Know the result ?
You can simply use console.log or alert like:
$http.post('v1/xyz/eeee res')
.success(function () {
console.log('api hit success')
})
.error(function () {
alert('api hit error')
})
Or you could use interceptors:
$httpProvider.interceptors.push(function() {
return {
'request': function(config) {
// statement to check if you are hitting your api
if (config.url.startsWith('/v1'))
alert('api hit')
}
};
});
I have two components BookInfo and AuthorLink. I want to fetch the book info and its author id from server and pass it to AuthorLink to use in componentDidMount to fetch the author name . However, the componentDidMount of AuthorLink run before the componentDidMount of BookInfo so authorid is null when the time it pass to AuthorLink.
How can I fetch the data and the data is ready before I pass it to the child?
var BookInfo = React.createClass({
.
.
.
componentDidMount: function() {
var id = this.props.params.id;
$.ajax({
url: '/api/books/' + id,
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error('#GET Error', status, err.toString());
}.bind(this)
});
},
render: function() {
return (
<AuthorLink authorid={this.state.data.authorid} />
);
}
});
var AuthorLink = React.createClass({
.
.
.
componentDidMount: function() {
$.ajax({
url: '/api/author/' + this.props.authorid,
dataType: 'json',
success: function(data) {
this.setState({authorname:data.authorname});
}.bind(this),
error: function(xhr, status, err) {
console.log('#GET Error', status, err.toString());
}.bind(this)
});
}
},
render: function() {
return (
<a href='#' onClick={this.linkOnClick} >
{this.state.authorname}
</a>
);
}
});
componentDidMount is just ran once per component on the initial render, hence it wont work in this case when we have to wait for the authorID in the BookInfo component.
You would be better off using componentWillReceiveProps in the AuthorLink component to fetch the author data, which is ran before render when, obviously, new props are received in the component. A tip is to also handle the case where the authorname isn't set in the render function, which will most likely be the case on the first render.
More on lifecycle methods her: https://facebook.github.io/react/docs/component-specs.html#updating-componentwillreceiveprops
You would have to move the ajax call into componentWillUpdate or componentWillReceiveProps and fire it when this.props.autherid changes (from null to an actual value)
Or you could delay the rendering of <AuthorLink/> itself by checking in the render if this.state.authorname is set:
render: function() {
var content = <div/>;
if(!!this.state.authorname) {
content = <a href='#' onClick={this.linkOnClick} >
{this.state.authorname}
</a>;
return content;
}
I'm trying to change the src attribute of an element after an AJAX call to a database. I have a default image url defined in getDefaultProps(), but after the AJAX call the image doesn't change.
PictureWidget is a child component of a Section component that controls the state (it also passes dataSource and dataSourceParams to PictureWidget). I'm not sure if I can use a local state for PictureWidget so I'm trying to do it through props.
This is my code:
var PictureWidget = React.createClass({
getDefaultProps: function() {
return {
url: 'https://d2o57arp16h0eu.cloudfront.net/echo/img/no_image_available.png'
}
},
componentDidMount: function() {
this.componentDidUpdate();
},
componentDidUpdate: function() {
// Grab img URL from DB
var postData = {
dataSource: this.props.params.dataSource,
dataSourceParams: this.props.dataSourceParams
};
$.ajax({
type: 'POST',
url: ajax_endpoint,
cache: false,
data: postData,
dataType: 'json',
success: function(response) {
if (response.data.length > 0) {
this.updateImage(response.data[0][0]);
}
}.bind(this),
error: function(response) {
this.render();
}
});
},
updateImage: function(url) {
console.log("Updating props.url with " + url);
this.props.url = url;
this.render();
},
render: function(imageURL) {
console.log("Rendering img " + this.props.url);
return React.createElement('div', {className: ' pure-u-' + this.props.columns},
React.createElement('div', {className: 'picture-widget'},
React.createElement('img', {src: this.props.url})
)
)
}
});
And this is my console log (forgive me for the poor formatting, still new to Overflow):
Rendering img https://d2o57arp16h0eu.cloudfront.net/echo/img/no_image_available.png
Updating props.url with http://vignette3.wikia.nocookie.net/animalcrossing/images/4/49/Tumblr_lvrcmvCpsS1qbeyouo1_500.jpg/revision/latest
Rendering img http://vignette3.wikia.nocookie.net/animalcrossing/images/4/49/Tumblr_lvrcmvCpsS1qbeyouo1_500.jpg/revision/latest
The initial render() grabs the default URL, but after the AJAX call this.props.url does get updated to the new value, so I would suspect React.createElement('img', {src: this.props.url}) is the trouble maker. Can I not update the src attribute this way?
This is what state is for. Try using getInitialState instead of getDefaultProps and bind url to this.state using setState().
getInitialState: function() {
return {
url: 'https://d2o57arp16h0eu.cloudfront.net/echo/img/no_image_available.png'
};
},
updateImage: function(url) {
console.log("Updating state.url with " + url);
this.setState({ url: url });
}