How to access nested object in React js 0.13.3 - javascript

The below added code is working fine in React js 0.10.0. I wanna run same code in 0.13.0 version also. My main requirement is accessing nested object as default object like "this.state.data.query.results.channel.item.condition.temp".
<!doctype html>
<html>
<head>
<title>Weather Widget</title>
<link rel="stylesheet" href="weather.css" />
<script src="http://fb.me/react-0.10.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.10.0.js"></script>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
</head>
<body>
<script type="text/jsx">
/*** #jsx React.DOM */
var weatherWidget = React.createClass({
loadData: function(){
$.ajax({
url: 'http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%2222102%22&format=json',
dataType : "jsonp",
cache: false,
success: function(data) {
console.log(data)
this.setState({data: data});
}.bind(this)
});
},
getInitialState: function(){
return {data: []};
},
componentWillMount: function(){
this.loadData();
},
render: function(){
return(
<div className="ww-container">
<div className="ww-current-condition">
<div className="ww-current-temperture">{this.state.data.query.results.channel.item.condition.temp}°</div>
</div>
</div>
)
}
});
React.renderComponent(<weatherWidget />, document.body);
</script>
</body>
</html>
http://jsfiddle.net/xJvY5/

You should set initial state, like so
getInitialState: function(){
return {
data: {
query: {
results: {
channel: {item: {condition: {temp: 0}}}
}
}
}
};
},
Example - (v 0.10.0)
Example - (v 0.13.3) - Note - that in version 0.13.3 you should use .render method instead of .renderComponent
or you can check data in render method, if data is undefined - show loading...., if state was updated you will see your data
getInitialState: function(){
return {};
},
render: function() {
if (!this.state.data) {
return <div>Loading...</div>;
}
....
}
Example - (v 0.13.3)

Related

VueJS api call leaving data undefined

I am learning VueJS 2.0 and I am connecting to an API where I want the value of some data to change on input change. Here is what the output says using the dev tools:
canadianDollar:undefined
europeanEuro:undefined
europeanPound:undefined
usd:"1232"
Whenever I put 1232 in the USD input field it doesn't return anything and leaves those properties as undefined. Here is the code.
new Vue({
el: '#app',
data: {
usd: '',
canadianDollar: '',
europeanPound: '',
europeanEuro: ''
},
// Watch methods
watch: {
usd: function() {
this.convertCurrency()
}
},
// Logic Methods
methods: {
convertCurrency: _.debounce(function() {
var app = this;
if (app.usd.length !== 0) {
// Show that the things are loading in.
app.canadianDollar = 'Searching...'
app.europeanPound = 'Searching...'
app.europeanEuro = 'Searching...'
console.log(app.usd)
axios.get("http://api.fixer.io/latest?base=USD&" + app.usd)
.then(function(response) {
app.canadianDollar = response.data.CAD
app.europeanPound = response.data.GBP
app.europeanEuro = response.data.EUR
})
.catch(function(error){
app.canadianDollar = "ERROR"
app.europeanPound = "ERROR"
app.europeanEuro = "ERROR"
})
}
}, 500)
}
})
and the HTML:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Vue</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" name="" value="" v-model="usd">
<ul>
<li>Canadian Dollar: {{canadianDollar}}</li>
<li>European Pound: {{europeanPound}}</li>
<li>European Euro: {{europeanEuro}}</li>
</ul>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js" charset="utf-8"></script>
<script src="index.js" charset="utf-8"></script>
</body>
</html>
When I type in a number it does give me the "Searching" part but disappears and nothing shows up.
I would recommend changing
then(function(response) {
app.canadianDollar = response.data.CAD
app.europeanPound = response.data.GBP
app.europeanEuro = response.data.EUR
})
to
then(function(response) {
console.log(response);
})
that was you can see what is being returned.
Also, axios.get("http://api.fixer.io/latest?base=USD&" + app.usd) should probably have a name like vulue:axios.get("http://api.fixer.io/latest?base=USD&VALUE=" + app.usd), but you'll have to check their api to see what it is meant to be called.
...
response.data.rates.CAD;
you have
response.data.CAD;
...
app.canadianDollar = response.data.rates.CAD * app.usd;

React Uncaught TypeError: this.setState is not a function

This is my first React code. I am trying to call a Restful web services from React.
It kept saying "Uncaught TypeError: this.setState is not a function". I couldn't figure out what's wrong with the code.
<!DOCTYPE html>
<html>
<head>
<title>React Flux</title>
<script src="https://fb.me/react-0.13.3.js"></script>
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
</head>
<body>
<div id="component"></div>
<script type="text/jsx">
var JavaEEWSTest = React.createClass({
getInitialState: function () {
return {text: ''};
},
componentDidMount: function(){
$.ajax({
url: "http://localhost:8080/rest/user/456"
}).then(function(data) {
this.setState({text: data.name});
}).bind(this)
},
render: function() {
return <div>Response - {this.state.text}</div>;
}
});
React.render(<JavaEEWSTest />, document.getElementById('component'));
</script>
</body>
</html>
You need set this to callback function
$.ajax({
url: "http://localhost:8080/rest/user/456"
}).then(function(data) {
this.setState({text: data.name});
}.bind(this))
^^^^^^^^^^^
but not for $.ajax/then - }).bind(this)

How to do infinite scroll in UI along with React JS?

Right now I am displaying all rows from Mysql DB to front end and I am using React JS as part of my project. I am struck with
1) How to get first 10 rows, then next 10 rows, then next 10 rows, till last row from Mysql DB using hibernate?
2) How can I invoke the ajax call in UI after 10 rows are scrolled.
The React JS code I am using now
<script type="text/babel">
var CommentBox = React.createClass({
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)
});
},
getInitialState: function(){
return {data: []};
},
componentDidMount: function(){
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function(){
return (
<div className="commentBox">
<CommentList data={this.state.data}/>
</div>
);
}
});
var CommentList = React.createClass({
render:function(){
var commentNodes = this.props.data.map(function(comment) {
return(
<Comment >
{comment}
</Comment>
);
});
return(
<div className="commentList">
{commentNodes}
</div>
);
}
});
var Comment = React.createClass({
rawMarkup: function() {
var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
return { __html: rawMarkup };
},
render: function(){
return (
<div className="comment">
<span dangerouslySetInnerHTML={this.rawMarkup()} />
</div>
)
}
});
ReactDOM.render(
<CommentBox url="/url/abc" pollInterval={10000}/>,
document.getElementById('content')
);
</script>
I came across the following piece of code w.r.t Infinite scroll, but not sure how to use this along with React JS
$(document).ready(function(){
$contentLoadTriggered = false;
$("#content-box").scroll(function(){
if($("#content-box").scrollTop() >= ($("#content-wrapper").height() - $("#content-box").height()) && $contentLoadTriggered == false)
{
$contentLoadTriggered = true;
$.get("infinitContentServlet", function(data){
$("#content-wrapper").append(data);
$contentLoadTriggered = false;
});
}
});
});
3) Also right now I am using .setFetchSize(10) in Hibernate. Not sure whether it will add next 10, and then next 10 as I am not able to test the scenario as my UI is not yet ready. I am struck and helpless. Please help me. Thanks.
You don't need to use setFetchSize(10) for a pagination. It is for an optimization purposes. For a pagination with Hibernate you can use this simply class (pageSize = 10 for your example)
public class Pagination {
public static final Pagination EMPTY = new Pagination(0, 0);
/** Page index, begins from 0. */
private final int pageIndex;
/** Objects on page count. */
private final int pageSize;
public Pagination(int pageIndex, int pageSize) {
this.pageIndex = pageIndex;
this.pageSize = pageSize;
}
public void addToCriteria(final Criteria criteria) {
if (this == EMPTY) {
return;
}
criteria.setMaxResults(pageSize);
criteria.setFirstResult(pageIndex * pageSize);
}
}
An example of using with Criteria.

Error: Birthday.search is not a function (AngularJS)

I'm coding a web app in html, AngularJS and REST (rest modified for my teachers).
My program should load participants in a select in the openning. But show i.e {{participants.name}} and not {{Jhon}}
The problem is at the moment that would load method "search".
Error:
"Error: Birthday.search is not a function
$scope.updateList#localhost:9000/birthday.js:26:1
#localhost:9000/birthday.js:31:5
e#localhost:9000/node_modules/angular/angular.min.js:36:313
Fe/this.$get
HTML:
<!DOCTYPE html>
<html lang="es" data-ng-app="birthdayApp">
<html>
<head>
<meta charset="utf-8">
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="node_modules/angular/angular.min.js"></script>
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="css/estilo.css">
<script src="birthday.js"></script>
</head>
[...]
<body>
<div class="container-fluid" data-ng-controller="BirthdayControllers as birthday">
[...]
<select size="2" class="col-lg-12 col-md-12 col-xs-12">
<option data-ng-repeat="participant in participants | filter:filter"> {{participant.name}} </option>
</select>
[...]
The head its ok?
AngularJS
'use strict';
var app = angular.module("birthdayApp", [])
app.factory('Birthday', function($http) {
return function(errorHandler) {
this.search = function(callback, errorHandler) {
$http.get('/participants').success(callback).catch(errorHandler);
}
}
});
/* Controllers */
app.controller("BirthdayControllers", function($scope, Birthday) {
$scope.participants = null;
var errorHandler = function(error) {
$scope.notificarError(error.data);
};
$scope.updateList = function() {
Birthday.search(function(data) { //here stop, here the problem!
$scope.participants = data;
}, errorHandler);
}
$scope.updateList();
[...]
});
My factories look different. Here's how I do mine:
app.factory('Birthday', function ($http) {
return {
search: function() {
return $http.get('/participants');
}
};
});
Controller would look like this:
Birthday.search().success(function(data) {
$scope.participants = data;
}).error(function(data, status, headers, config) {
//handle the error
});
You need to return a factory object from the function not another function.
So modify your code like this:
app.factory('Birthday', function($http) {
return {
search: function() {
return $http.get('/participants');
}
};
});
It's better to handle the callbacks in the controller, so call the factory method like this:
Birthday.search().success(function(data) {
$scope.participants = data;
}).catch(function(error) {
$scope.notificarError(error.data);
});

Nested Objects in ReactJS

I was going through the react getting started tutorial and have run into a problem with an experiment I am doing. I am able log an object but in the console, I get the following error:
Uncaught TypeError: Cannot read property 'results' of undefined
I can log the object so I know my api call is successfully but for some reason my react state does not seem to get updated. I think that my render function is happening before my data object gets updated from the API but not sure how to fix it.
http://jsfiddle.net/xJvY5/
<!doctype html>
<html>
<head>
<title>Weather Widget</title>
<link rel="stylesheet" href="weather.css" />
<script src="http://fb.me/react-0.10.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.10.0.js"></script>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
</head>
<body>
<script type="text/jsx">
/*** #jsx React.DOM */
var weatherWidget = React.createClass({
loadData: function(){
$.ajax({
url: 'http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%2222102%22&format=json',
dataType : "jsonp",
cache: false,
success: function(data) {
console.log(data)
this.setState({data: data});
}.bind(this)
});
},
getInitialState: function(){
return {data: []};
},
componentWillMount: function(){
this.loadData();
},
render: function(){
return(
<div className="ww-container">
<div className="ww-current-condition">
<div className="ww-current-temperture">{this.state.data.query.results.channel.item.condition.temp}°</div>
</div>
</div>
)
}
});
React.renderComponent(<weatherWidget />, document.body);
</script>
</body>
</html>
The problem is that React is trying to access the result of the API call while it hasn't been fetched yet. You should add null checks when accessing nested objects (this is a javascript issue rather than something React-specific).
Secondly, while the data is unavailable, your component will still try to render something. React renders your component the moment you inject it into the page, so consider showing a "loading" indicator while the API result has not been saved to state.
Here is a fork of your fiddle with appropriate null checks & "loading indicator":
http://jsfiddle.net/jxg/9WZA5/
render: function(){
var degrees = this.state.item ? this.state.item.condition.temp : 'loading...';
return(
<div className="ww-container">
<div className="ww-current-condition">
<div className="ww-current-temperture">{degrees}°</div>
</div>
</div>
);

Categories