I am looking into ReactJS. I've created database and added a table with some simple data.
Next I created a php file that will display the data in json format like this:
[{"ID":"1","Name":"name","Color":"green"}]
Next I've created a reactjs skeleton page and I'm trying to get it to read and display the json data but cannot find a simple example anywhere.
How can I get reactjs to read json from a url?
I created a fiddle which is a simple getting started and will give you an idea how to proceed.
Also, I think you will find this example from React Docs about loading data from ajax helpful. Code from there is as follows:
var UserGist = React.createClass({
getInitialState: function() {
return {
username: '',
lastGistUrl: ''
};
},
componentDidMount: function() {
$.get(this.props.source, function(result) {
var lastGist = result[0];
if (this.isMounted()) {
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}
}.bind(this));
},
render: function() {
return (
<div>
{this.state.username}'s last gist is
<a href={this.state.lastGistUrl}>here</a>.
</div>
);
}
});
React.render(
<UserGist source="https://api.github.com/users/octocat/gists" />,
mountNode
);
Related
I have the react application uses the server side rendering. I used react-helmet as for display dynamic meta tags. Everything is setups perfectly. Also the dynamic meta tags are being display to the browser correctly but at server side it takes values undefined. Is anyone tell me its solution what to do.
For example :
var React = require('react');
var Helmet = require('react-helmet');
var About = React.createClass({
getInitialState: function(){
return {
title: "",
description: "",
}
},
componentDidMount: function(){
$.ajax({
url: api_url+'/get_meta',
type: 'POST',
dataType: 'json',
async: false,
success: function( response ) {
if( response.status==200 ){
this.setState({title: response.title, description: response.title });
}
}
});
},
render: function() {
var title = this.state.title;
var description = this.state.description;
return (
<div>
<Helmet
title={title}
meta={[
{"name": "description", "content": description }
]}
/>
<p>
This is the title page
</p>
</div>
);
}
});
module.exports = About;
When I view the source it doesn't display anything in meta tag, but when I inspect the browser element it shows the meta tag value.
After debugging a while, I found the issue, the component is renders both server and client side, So at server side it is rendering the component with initial state only, that's why the value is not being display.
Please anyone suggest what to do?
I am new to React.js and trying to render the result from an ajax call using react but the data is not coming to the render() function. If you know any other best way to solve this issue or make an ajax call in react then please let mention the link for the same. Need to render data in react from an API.Below is the javascript for the same. The value is coming in componentDidMount method and result is having the value. But when I try to access in the render, then its empty. I tried to assign value to a global object array but that is also not working. Any solutions for this.The link mentioned in the post for fetching data is a working link. You can call that link in the browser and check for json field.
var UserGist = React.createClass({
getInitialState: function() {
return {
username: '',
lastGistUrl: ''
};
},
componentDidMount: function() {
this.serverRequest = $.get(this.props.source, function(result) {
this.setState({
username = result.description,
lastGistUrl = result.html_url
})
}.bind(this));
},
componentWillUnmount: function() {
this.serverRequest.abort();
},
render: function() {
React.createElement("div", null, this.state.username, " 's last gist's url is ",
React.createElement("div", null, this.state.lastGistUrl, ""), ".")
}
});
ReactDOM.render(React.createElement(UserGist, { source: "https://api.github.com/users/octocat/gists" }), document.getElementById('container'));
Fiddler link
Your code contains syntax errors. Replace = with :.
componentDidMount: function() {
this.serverRequest = $.get(this.props.source, function(result) {
this.setState({
username: result.description,
lastGistUrl: result.html_url
})
}.bind(this));
},
More errors to come:
render missing return statement. Should be return React.createElement
result is an array not an object. You need to somehow handle this. For example pick the first element result = result[0]
setState is method. You should call it not make an assignment setState=({}) should be setState({}) This one was in demo code.
See fixed demo.
The header of my site has 10 category images (links). Each uses React-Router's Link to route to each category's respective categoryShow.
The link works from categoryIndex, but it no longer works when being clicked form a cagetoryShow. It properly updates the browser when clicking on it, for example it does pushState to /cateories/18 and /categories/2, but the browser doesn't refresh.
Worth noting is the link works from every other Index-type and Show-type page. It just doesn't work from categoryShow in particular. I wonder if successive clicks to the same name, eg Link to="categoryShow", somehow keeps the router from doing a page refresh?. Edit: I tried changing that to Link to= {"/categories/" + this.props.id } and it does the same thing.
Here's the noteworthy component structure. All the data is successfully being passed all the way through updating the URL. It's just that the page does't refresh in one particular case:
-categoryShow
-header (fetches and passes category data to child)
-headerMenu (receives category data, passes on to child)
-headerMenuCard (receives category data, uses the id in the link seen below)
headerMenuCard:
var HeaderMenuCard = React.createClass({
...
return(
<div >
<Link to="categoryShow" params={{id: this.props.id}} ></Link>
</div>
)
})
Here's CategoryShow, which is where the link routes to:
var CategoryShow = React.createClass({
getInitialState: function(){
return{
didFetchData: false,
items: [],
userID: localStorage.getItem('userID'),
headerImage: "../categories.png"
}
},
componentDidMount: function(){
this.fetchData()
},
fetchData: function(){
var data = {
userID: this.state.userID
}
var params = this.props.params.id
$.ajax({
type: "GET",
url: "/categories/" + params,
data: data,
dataType: 'json',
success: function(data){
this.setState({didFetchData: 'true', items: data.items})
}.bind(this),
error: function(data){
alert("error! couldn't fetch category data")
}
})
},
render: function(){
var itemArray = this.state.items.map(function(item){
return <ItemCard name={item.name} key={item.id} id={item.id} photo_url={item.photo_url} description={item.description} userID={localStorage.getItem('userID')} like_status={item.like_status} />
})
return(
<div>
<Header />
<section className="body-wrapper">
{itemArray}
</section>
</div>
)
}
})
You'll receive new parameters in props and thus you only need to run fetchData or any other logic in componentWillReceiveProps or componentWillUpdate.
I do not want to use Babel/ES6 yet because reasons. I have been watching the egghead.io videos on react/reflux and have a component here I am rendering. It connects to the randomuser API and pulls 10 users into the store, when the store is updated it renders the user data onto the page. With the ES6 code shown in the video it allows nice interpolation of tags, so that but in my case I am just using lodash as _.map which operates slightly differently, and I am unable to find a way to render tag interpolation or even line breaks, as React renders out the elements as all children of one parent tag contained inside its own span tags.
The rendered code looks like this:
and my code is here:
var React = require('react');
var Reflux = require('reflux');
var request = require('superagent');
var _ = require('lodash');
var store = Reflux.createStore({
data: {users:[]},
init: function(){
request
.get("http://api.randomuser.me/?results=10")
.end(function(err,res){
if(err){
console.log(err)
}else {
var FirstName = res.body.results[0].user.name.first;
var LastName = res.body.results[0].user.name.last;
var picture = res.body.results[0].user.picture.thumbnail;
store.trigger({users:res.body.results})
}
});
},
getInitialState(){
return this.data;
}
});
var Name = React.createClass({
mixins:[Reflux.connect(store)],
render: function(){
return(
<div>
{_.map(this.state.users,function(n){
fName=n.user.name.first
lName=n.user.name.last
picture = n.user.picture.thumbnail;
return ""+fName+" "+lName + " " + picture
})
}
</div>
)
}
});
React.render(<Name />, document.getElementById('users'));
Any suggestions or advice would be greatly appreciated! also the egghead.io videos are top notch, i must give credit where it is due!
Personally, I try to avoid doing interpolation in JSX tags. JSX gives you a pretty solid API for constructing DOM elements! In this case, I'd do something like this:
render: function() {
var userElements = _.map(this.state.users,function(n){
var fName=n.user.name.first
var lName=n.user.name.last
var pictureURL = n.user.picture.thumbnail;
return (
<div className='user'>
<span className='first-name'>{fname}</span>
<span className='last-name'>{lname}</span>
<img className='picture' src={pictureURL}></img>
</div>
)
})
return (
<div className='user-container'>
{userElements}
</div>
)
}
I'm building a React+Reflux application that, among other things, allows for the creation/deletion/editing of categories. So far I'm able to display all categories and handle creation/deletion of categories within a React component through associated stores and actions. This all works great, updates the database and re-renders the component as expected. My sticking point is when trying to drill down into a specific existing category in order to edit it.
I think I somehow need to pass a category Id to a store which will then pass it along to a php/sql query via an ajax call in order to get/set data specific to that particular category. If I bypass the store altogether and put the ajax call within the component itself I'm able to get it working via a url parameter with React-router (no auto re-render of course) but I haven't been able to figure out how to accomplish this through a store.
In other words, this more or less works:
"ManageCategories" React component that uses CategoryStore to list all categories each wrapped in an anchor tag that passes the category Id along to "ManageCategory" route/component
The "ManageCategory" component uses the category Id param directly in an ajax call within its getInitialState method to display data specific to the category
However, I think below is the more correct Reflux way to do this but I'm not sure how to get it to work:
"ManageCategories" component same as above
"ManageCategory" component that somehow passes its category Id param to the CategoryStore (or maybe a different "IndividualCategoryStore"?) which returns only data specific to that category and handles updates/edits to that category
I was able to get a sort of clunky version of this working by adding a new method ("getCategoryData") to the CategoryStore that is called in the getInitialState method of the "ManageCategory" component and is passed the categoryId param. This results in a flash of all categories (from the CategoryStore's getDefaultData) followed by the correct single category listing (from the component's getInitialState).
I feel fairly comfortable with the concepts behind React+Reflux but at this point I think it's likely I'm misunderstanding something fundamental. Worked on this particular issue for more than a week but none of the examples/tutorials/docs I've found address the specific question of passing a variable to a data store.
Actions:
var Actions = Reflux.createActions([
"createCategory",
"deleteCategory",
"editCategory"
]);
CategoryStore:
var CategoryStore = Reflux.createStore({
listenables: [Actions],
onCreateCategory: function(catName) {
// ajax call to create new category that calls updateCategories on success
},
onDeleteCategory: function(catId) {
// ajax call to delete category that calls updateCategories on success
},
updateCategories: function(){
$.ajax({
url: url + '?action=getAllCategories',
async: false,
dataType: 'json',
success: function(categoryData) {
this.categories = categoryData;
}.bind(this),
error: function(xhr, status, err) {
console.error(url, status, err.toString());
}.bind(this)
});
this.trigger(this.categories);
},
getDefaultData: function() {
$.ajax({
url: url + '?action=getAllCategories',
async: false,
dataType: 'json',
success: function(categoryData) {
this.categories = categoryData;
}.bind(this),
error: function(xhr, status, err) {
console.error(url, status, err.toString());
}.bind(this)
});
return this.categories;
}
});
Category Component:
var Category = React.createClass({
handleDeleteCategory: function() {
Actions.deleteCategory(this.props.id);
},
render: function() {
return (
<li className="category">
<IconButton icon="action-highlight-remove" onClick={this.handleDeleteCategory} />
<h5><a href={"/#/manage-category/" + this.props.id}>{this.props.name} ({this.props.id})</a></h5>
</li>
);
}
});
ManageCategories Component:
var ManageCategories = React.createClass({
mixins: [
Reflux.connect(CategoryStore, "categories")
],
getInitialState: function() {
return {
categories: []
};
},
handleCreateCategory: function() {
// category creation code
},
render: function() {
var categoryNodes = this.state.categories.map(function(category) {
return (
<Category name={category.name} id={category.id} />
)
});
return (
<div className="dev-tools-container">
<h1>Developer Tools</h1>
<div className="categories">
<h3>Categories</h3>
<ul>
{categoryNodes}
</ul>
<h4>Create New Category:</h4>
<form>
<label htmlFor="new-category-name">Category Name</label> <input type="text" id="new-category-name" /><br />
<PaperButton label="Create" primary={true} onClick={this.handleCreateCategory} />
</form>
</div>
</div>
);
}
});
Thanks in advance for any insights or assistance.
After finally posting my question here I think I may have figured out where I was going astray all along. I was thinking in terms of passing the category Id to the store to filter the data therein when all I really need to do is take the full collection of data from the store and consume it selectively within the component.
So once routed to the ManageCategory component with the catId passed along as a url param, all I need to do is filter the data based on the catId.
For example, once in the ManageCategory component I can use lodash to filter and pluck the name value of the current category, as below. No need to edit the collection of data stored in the CategoryStore at all.
var ManageCategory = React.createClass({
mixins: [
Reflux.connect(CategoryStore, "categoryData")
],
getInitialState: function() {
return {
categoryData: []
};
},
render: function() {
var categoryName = _.chain(this.state.categoryData)
.filter({"id": this.props.params.catid})
.pluck("name");
return (
<div className="category-container">
<h1>{categoryName}</h1>
</div>
);
}
});
Feel free to let me know if there's a better way of doing this but for now this is exactly what I needed. Hopefully something from all of this will be helpful to someone else too.