react - json from url - javascript

I'm going through the react tutorial here -
http://facebook.github.io/react/docs/tutorial.html
And I'm having problems on step 11 "Fetching from the Server"
Here is my .js file -
var WGGroupList = React.createClass({
render: function() {
var wggroupNodes = this.state.data.map(function(wggroup) {
return (
<WGGroup name={wggroup.name} key={wggroup.id}>
{wggroup.description}
</WGGroup>
);
});
return (
<div className="wggroupList">
{wggroupNodes}
</div>
);
}
});
var WGGroupForm = React.createClass({
render: function() {
return (
<div className="wggroupForm">
Hello, world! I am a Widget Group Form.
</div>
);
}
});
var WGGroupBox = React.createClass({
getInitialState: function() {
return {data: []};
},
render: function() {
return (
<div className="wggroupBox">
<h1>Description</h1>
<WGGroupList data={this.state.data} />
// <WGGroupList data={this.props.data} />
<WGGroupForm />
</div>
);
}
});
var WGGroup = React.createClass({
render: function() {
return (
<div className="wggroups">
<h2 className="wggroupName">
{this.state.data.name}
</h2>
{this.state.data.children}
</div>
);
}
});
ReactDOM.render(
<WGGroupBox data="http://servername/api/wggroups/?format=json" />,
// <WGGroupBox data={data} />,
document.getElementById('content')
);
It works if I do the example previous with the data hardcoded -
var data = [
{id: 1, name: "Primary Widgets", description: "This is my Primary Widget group"},
{id: 2, name: "Secondary Widgets", description: "This is my secondary Widget group"}
];
The json served from the API is exactly the same format as above. So why, if using my URL do I get the following -
Uncaught TypeError: Cannot read property 'data' of null
It's failing on this line -
var wggroupNodes = this.state.data.map(function(wggroup) {
If I debug in my browser the datasource is not showing up so I'm guessing the issue is why is it not loading the url data?

I checked step 11 in the Tutorial and came across this sentence:
"Note: the code will not be working at this step."
At step 13 the function that fetches data from a server is introduced.. right now you are just passing a url-string around.

Related

React: Search Results not being displayed?

So I am learning react.js, and I am developing a quick search engine using the GitHub API of users.
The API side of the project works fine (I have tested by manually entering names into the area)
Its the search build in react that is not working.
(FYI: I am using Plunker which has react support)
script.jsx
var Card = React.createClass({
getInitialState: function(){
return{};
},
componentDidMount: function(){
var component = this;
$.get("https://api.github.com/users/" + this.props.login, function(data){
component.setState(data);
});
},
render: function(){
return(
<div>
<img src={this.state.avatar_url} width="100"/>
<h3>{this.state.name}</h3>
<hr/>
</div>
);
}
});
var Form = React.createClass({
handleSubmit: function(e){
e.preventDefault();
var loginInput = React.findDOMNode(this.refs.login);
this.props.addCard(loginInput.value);
loginInput.value = '';
},
render: function(){
return(
<form onSubmit={this.handleSubmit}>
<input placeholder="Enter Github Name" ref="login"/>
<button>Search</button>
</form>
);
}
});
var Main = React.createClass({
getInitialState: function(){
return {logins: []};
},
addCard: function(loginToAdd){
this.setState({logins: this.state.logins.concat(loginToAdd)});
},
render: function() {
var cards = this.state.logins.map(function(login){
return (<Card login={login} />);
});
return(
<div>
<Form addCard={this.addCard} />
{cards}
</div>
)
}
});
ReactDOM.render(<Main />, document.getElementById("root"));
The problem was (if you check console), that you had a duplicate script tag in the <head> which you didn't need. And also, you were doing React.findDOMNode instead of ReactDOM.findDOMNode
Line 25 of your JSX file:
var loginInput = ReactDOM.findDOMNode(this.refs.login);
That said, you don't need to do ReactDOM.findDOMNode. You can just use this.refs.login

React - Issue with syntax

I'm trying to test React out for myself. I got a simple "Hello World" message outputted successfully, so I tried taking this a step further and loop through data.
I'm getting a "waiting for roots to load…to reload the inspector” error, which after Googling tells me I have an issue with my syntax. I just can't find it... so your help is much appreciated!
var data = [
{perc:"2.2%", year:"5"},
{perc:"3.2%", year: "7"}
]
var Rates = React.createClass({
render: function(){
return (
<div>
<RateList data={this.props.rates} />
</div>
)
}
});
var Rate = React.createClass({
render: function(){
return (
<div>
<ul>
<li>{this.props.percent}</li>
</ul>
</div>
)
}
});
var RateList = React.createClass({
render: function(){
return (
<div>
<ul>
{ this.props.data.map(function(rate){
return <Rate percent={rate.perc} />
}) }
</ul>
</div>
)
}
});
ReactDOM.render(<Rates rates={data} />, document.getElementById("wow"));
It seems you could simplify a little.
var data = [
{perc:"2.2%", year:"5"},
{perc:"3.2%", year: "7"}
]
var RateList = React.createClass({
render: function(){
return (
<div>
<ul>
{ this.props.rates.map(function(rate){
return <li>{rate.perc}</li>
}) }
</ul>
</div>
)
}
});
ReactDOM.render(<RateList rates={data} />, document.getElementById("wow"));

React Search filter function

Basically what my code does is display a table list of names with a search bar at the top that filters the list as you type in a value.
The problem I am having with my code at the moment is adding an if statement to the DisplayTable component. I dont want it to display all the stored data but just display the ones that have been inputted by the user in the search bar {queryText}
Please Ignore the tableData variable
var InstantBox = React.createClass({
doSearch:function(queryText){
console.log(queryText)
//get query result
var queryResult=[];
this.props.data.forEach(function(person){
if(person.name.toLowerCase().indexOf(queryText)!=-1)
queryResult.push(person);
});
this.setState({
query:queryText,
filteredData: queryResult
})
},
getInitialState:function(){
return{
query:'',
filteredData: this.props.data
}
},
render:function(){
return (
<div className="InstantBox">
<h2>Who is Richer?</h2>
<SearchBox query={this.state.query} doSearch={this.doSearch}/>
<DisplayTable data={this.state.filteredData}/>
</div>
);
}
});
var SearchBox = React.createClass({
doSearch:function(){
var query=this.refs.searchInput.getDOMNode().value; // this is the search text
this.props.doSearch(query);
},
render:function(){
return <input className="searchbar-edit" type="text" ref="searchInput" placeholder="Search Name" value={this.props.query} onChange={this.doSearch}/>
}
});
var DisplayTable = React.createClass({
doSearch:function(queryText){
console.log(queryText)
//get query result
var queryResult=[];
this.props.data.forEach(function(person){
if(person.name.toLowerCase().indexOf(queryText)!=-1)
queryResult.push(person);
});
this.setState({
query:queryText,
filteredData: queryResult
})
},
render:function(){
//making the rows to display
var rows=[];
this.props.data.forEach(function(person) {
rows.push(<tr><td>{person.image}</td></tr>)
rows.push(<tr><td>{person.name}</td></tr>)
});
//returning the table
return(
<table>
<tbody>{rows}</tbody>
</table>
);
}
});
var tableData=[
{
name:'Paul mak',
image: <img width="50" src="./images/profile_img.png"/>,
},
];
var dataSource=[
{
name:'Paul mak',
image: <img width="50" src="./images/profile_img.png"/>,
},
{
name:'John Doe',
image : '002'
},
{
name:'Sachin Tendulkar',
image : '003'
}];
React.render(
<InstantBox data={dataSource}/>,
document.getElementById('content1')
);
Try something like this:
var InstantBox = React.createClass({
doSearch:function(queryText){
console.log(queryText)
//get query result
var queryResult=[];
this.props.data.forEach(function(person){
if(person.name.toLowerCase().indexOf(queryText)!=-1)
queryResult.push(person);
});
this.setState({
query:queryText,
filteredData: queryResult
})
},
getInitialState:function(){
return{
query: '',
filteredData: undefined
}
},
renderResults: function() {
if (this.state.filteredData) {
return (
<DisplayTable data={this.state.filteredData}/>
);
}
},
render:function(){
return (
<div className="InstantBox">
<h2>Who is Richer?</h2>
<SearchBox query={this.state.query} doSearch={this.doSearch}/>
{this.renderResults()}
</div>
);
}
});
What I've changed from your code is I changed this.state.filteredData to be undefined (in fact you could just remove it entirely, but I thought this was clearer for you right now) in your initial state. This way when you first render the box, there's no filteredData and your <DisplayTable /> doesn't render. As soon as you run your doSearch callback from <SearchBox /> it will populate filteredData and display it.
To extend this you could also check when this.state.query is undefined again or blank (eg with : this.state.query.length) to remove <DisplayTable /> from the dom again if there is no query / no results.
Remember render functions are still just javascript. Anything you wrap in {} inside JSX will be evaluated. We could have just had this logic inside the render function and be doing something like var displayTable = <DisplayTable />; and then including {displayTable} in the returned JSX and it would have been the same. I personally just prefer splitting render logic up among different functions :)

How to transfer props in react v0.13?

I'm trying to learn react for my first javascript project and as a start creating a very simple code that adds two numbers entered in a text box. The result is re-rendered as a number is typed. This worked for me on react v0.11.
var App = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {
payment: 0,
payment2: 0
};
},
render: function() {
var total = parseInt(this.state.payment, 10) +
parseInt(this.state.payment2, 10);
return (
<div>
<Payment {...this.props} valueLink={this.linkState('payment')}/><span>+</span>
<Payment {...this.props} valueLink={this.linkState('payment2')}/><span>=</span>
{ total }
</div>
);
}
});
var Payment = React.createClass({
render: function() {
return this.transferPropsTo(
<input type="text" />
);
}
});
React.render(
<App />,
document.getElementById('app')
);
However, it seems like the transferPropsTo() function was removed in v0.13. How do I do the equivalent in the latest version.
You can pass {...this.props} in the input tag:
var Payment = React.createClass({
render: function() {
return (
<input type="text" {...this.props} />
);
}
});
This uses the JSX spread attributes feature.

TypeError: this.props.data.map is not a function, but data is a list

I have written code from the ReactJs site here while working through their comment box tutorial. Yet for some reason it is giving me an error about map:
Uncaught TypeError: this.props.data.map is not a function
Specifically it is complaining about line 7: var commentNodes = this.props.data.map(function (comment){ .. etc.. }
This error is particularly confusing since data is a list. Here is the full code displaying that:
var CommentList = React.createClass({
render: function(){
console.log(data)
var commentNodes = this.props.data.map(function (comment){
return (<Comment author={comment.author}>
{comment.text}
</Comment>);
});
return (<div className="commentList">
{commentNodes}
</div>);
}
});
var Comment = React.createClass({
render: function(){
return (<div className="comment">
<h2 className="commentAuthor">
{this.props.author}
</h2>
{this.props.children}
</div> );
}
});
var CommentForm = React.createClass({
render: function(){
return (<div className="commentForm">I am a comment form!</div>);
}
});
var CommentBox = React.createClass({
render: function() {
return (<div className="commentBox">
<CommentList data="{this.props.data}" />
<CommentForm />
</div>);
}
});
var data = [
{author: "Pete Hunt", text: "This is one comment"},
{author: "Jordan Walke", text: "This is *another* comment"}
];
React.render(<CommentBox data={data} />, document.getElementById('content'));
This shouldn't be wrapped in a string data="{this.props.data}". Just remove the quotes and it should work.

Categories

Resources