How to solve infinity loading either in your desktop or mobile? By now, everyone is familiar with JQuery, but we all know is JQuery cannot handle such large amount of data to load. React JS is the best solution for this problem. JQuery and other libraries interacts directly with DOM to load any data; but React JS is specifically designed in such a way that it has a mid interactive layer called Virtual DOM which in turn interacts with DOM(as shown in the diagram below). This Virtual DOM helps in data loading very faster.
Download Script Live Demo
React is a big library; Initially, for the developers it may look bit complicated to code using React JS, but eventually we feel it very easy once we get used to it. React is easy to maintain too. I specifically suggest React JS for mobile applications. Applications like Facebook, twitter uses React. React JS is not a framework, its a library for View component. Take a look at the demo, how React works for our Wall System.
How to Start React Application
You have to include following libraries to start React application, React is using JSX(Javascript with XML on it) standard and it is not a globally accepted standard, so we are using Babel compiler browser.min.js and JavaScript code type should be "text/babel"<!DOCTYPE html>
<html lang="en">
<head>
<title>React JS</title>
<link rel="stylesheet" href="css/wall.css" />
<script src="build/react.min.js"></script>
<script src="build/react-dom.min.js"></script>
<script src="build/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
</body>
<script type="text/babel">
// React Code ....
</script>
</html>
<html lang="en">
<head>
<title>React JS</title>
<link rel="stylesheet" href="css/wall.css" />
<script src="build/react.min.js"></script>
<script src="build/react-dom.min.js"></script>
<script src="build/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
</body>
<script type="text/babel">
// React Code ....
</script>
</html>
Hello World
React structure for printing value in HTML DOM.
<script type="text/babel">
ReactDOM.render(
<div>Hello World</div>,
document.getElementById('container')
);
</script>
ReactDOM.render(
<div>Hello World</div>,
document.getElementById('container')
);
</script>
Hello World Component
React is all about components, here is the stucture for HelloWorld component. Component name must start with capital letter.
<script type="text/babel">
var HelloWorld=React.createClass({
render: function(){
return(
<div>Hello World</div>
);
}
});
ReactDOM.render(
<HelloWorld/>,
document.getElementById('container')
);
</script>
var HelloWorld=React.createClass({
render: function(){
return(
<div>Hello World</div>
);
}
});
ReactDOM.render(
<HelloWorld/>,
document.getElementById('container')
);
</script>
Getting started with Wall System - Step 1
Hope you like my previous post Angular JS Facebook Wall System with Multiple Bindings, just follow the tutorial for HTML & CSS design for Wall System. <script type="text/babel">
var WallContainer=React.createClass({
render: function(){
return(
<div id="wallContainer">
<h1>Social Network System with React JS Demo</h1>
<WallFeed/>
</div>
);
}
});
ReactDOM.render(
<WallContainer/>,
document.getElementById('container')
);
</script>
var WallContainer=React.createClass({
render: function(){
return(
<div id="wallContainer">
<h1>Social Network System with React JS Demo</h1>
<WallFeed/>
</div>
);
}
});
ReactDOM.render(
<WallContainer/>,
document.getElementById('container')
);
</script>
Create a main component called WallContainer, this is going to render within HTML ID container. Included a new component called WallFeed
WallFeed Component
This component divided into two components WallFrom & WallUpdated.
var WallFeed=React.createClass({
render: function(){
return(
<div>
<WallForm/>
<WallUpdates />
</div>
);
}
});
render: function(){
return(
<div>
<WallForm/>
<WallUpdates />
</div>
);
}
});
WallForm
This contains wall update form operations.
var WallForm=React.createClass({
render: function(){
return(
<form >
<textarea></textarea>
<input type='submit' value='Post' id='wallPost'/>
</form>
);
}
});
render: function(){
return(
<form >
<textarea></textarea>
<input type='submit' value='Post' id='wallPost'/>
</form>
);
}
});
WallUpdates
This component contains wall updates operation, follow the steps you will find more about this.
var WallUpdates=React.createClass({
render: function(){
return(
<div id="wallFeed">
//News Feed Uploads Loop
</div>
);
},
});
render: function(){
return(
<div id="wallFeed">
//News Feed Uploads Loop
</div>
);
},
});
Include Jquery for Ajax Calls
You have to include Jquery library for ajax features to communicate with APIs or server side operations.
<script src="build/jquery.min.js"></script>
<script src="build/ajaxPostReact.js"></script>
<script src="build/ajaxPostReact.js"></script>
ajaxPostReact.js
Create a simple Jquery ajax function for reusability, this will minimize your code.
function ajaxPostReact(url, dataPost, reactThis, success)
{
$.ajax({
type:"POST",
url: url,
data:dataPost,
dataType:"json",
cache:false,
timeout:20000,
beforeSend :function(data) { }.bind(this),
success:function(data){success.call(this, data);}.bind(this),
error:function(data){}.bind(this)
});
}
{
$.ajax({
type:"POST",
url: url,
data:dataPost,
dataType:"json",
cache:false,
timeout:20000,
beforeSend :function(data) { }.bind(this),
success:function(data){success.call(this, data);}.bind(this),
error:function(data){}.bind(this)
});
}
Load User Updates Data to WallFeed Component
Now go to WallFeed component and include following functions. Here getInitialState and componentDidMount are React builtin functions. Using getInitialState you can initialize variables and componentDidMount is loads with component.
var WallFeed=React.createClass({
getInitialState: function(){
return {data: []};
},
updatesFromServer: function()
{
var dataPost='';
var reactThis=this;
ajaxPostReact('newsFeed.php', dataPost, reactThis, function(data){
reactThis.setState({data: data.updates});
});
},
componentDidMount: function()
{
this.updatesFromServer();
},
render: function(){
return(
<div>
<WallForm/>
<WallUpdates data={this.state.data}/>
</div>
);
}
});
getInitialState: function(){
return {data: []};
},
updatesFromServer: function()
{
var dataPost='';
var reactThis=this;
ajaxPostReact('newsFeed.php', dataPost, reactThis, function(data){
reactThis.setState({data: data.updates});
});
},
componentDidMount: function()
{
this.updatesFromServer();
},
render: function(){
return(
<div>
<WallForm/>
<WallUpdates data={this.state.data}/>
</div>
);
}
});
updatesFromServer function is contains ajax operation to load user updates data, using this.state assigning updates data to the WallUpdates component.
Read more about Create a RESTful services using Slim and Wall Database Design
JSON Response newsFeed.php
Following JSON data we need to render with WallUpdates component.
{
"updates": [
{
"user_id": "1",
"name": "Srinivas Tamada",
"profile_pic": "pic.png",
"update_id": "62",
"user_update": "The Wall Script http://www.thewallscript.com",
"created": "1464062121",
"comments": [
{
"com_id": "62",
"uid_fk": "80",
"comment": "Nice",
"created": "1468871427",
"like_count": "0",
"name": "Arun Shekar",
"profile_pic": "pic.jpg",
"timeAgo": "2016-07-18T21:50:27+02:00"
},
//Other Comments
]
},
//Other Udates
]
}
"updates": [
{
"user_id": "1",
"name": "Srinivas Tamada",
"profile_pic": "pic.png",
"update_id": "62",
"user_update": "The Wall Script http://www.thewallscript.com",
"created": "1464062121",
"comments": [
{
"com_id": "62",
"uid_fk": "80",
"comment": "Nice",
"created": "1468871427",
"like_count": "0",
"name": "Arun Shekar",
"profile_pic": "pic.jpg",
"timeAgo": "2016-07-18T21:50:27+02:00"
},
//Other Comments
]
},
//Other Udates
]
}
WallUpdates Rendering with User Updates Data
Now go to WallUpdates component and modify in following way, using this.props calling the WallUpdates component state value.
var WallUpdates=React.createClass({
render: function(){
var updatesEach=this.props.data.map(function(update, index)
{
return(
<div className="feedBody" key={update.created}>
<img src={update.profile_pic} className="feedImg" />
<div className="feedText">
<b>{update.name}</b>
<a href="#" className="feedDelete">X</a>
{update.user_update}
</div>
//Comments Block
</div>
)
}, this);
return(
<div id="wallFeed">
{updatesEach}
</div>
);
},
});
render: function(){
var updatesEach=this.props.data.map(function(update, index)
{
return(
<div className="feedBody" key={update.created}>
<img src={update.profile_pic} className="feedImg" />
<div className="feedText">
<b>{update.name}</b>
<a href="#" className="feedDelete">X</a>
{update.user_update}
</div>
//Comments Block
</div>
)
}, this);
return(
<div id="wallFeed">
{updatesEach}
</div>
);
},
});
Step 1 Demo
Step 2
WallForm
Using findDOMNode focusing textarea box ref value updateInput.
var WallForm=React.createClass({
getInitialState: function(){
return { user_update: ''};
},
componentDidMount: function(){
ReactDOM.findDOMNode(this.refs.updateInput).focus();
},
render: function(){
return(
<form >
<textarea ref="updateInput" value={this.state.user_update}></textarea>
<input type='submit' value='Post' id='wallPost'/>
</form>
);
}
});
getInitialState: function(){
return { user_update: ''};
},
componentDidMount: function(){
ReactDOM.findDOMNode(this.refs.updateInput).focus();
},
render: function(){
return(
<form >
<textarea ref="updateInput" value={this.state.user_update}></textarea>
<input type='submit' value='Post' id='wallPost'/>
</form>
);
}
});
Getting Update Box Input Value
Write a function get the input state value using e.target.value. Set user_update value using React.setState function.
updateChange: function(e){
this.setState({user_update: e.target.value });
}
this.setState({user_update: e.target.value });
}
onChange Input
Every input change triggers updateChange function.
<textarea ref="updateInput" value={this.state.user_update}
onChange={this.updateChange}></textarea>
onChange={this.updateChange}></textarea>
Update Form Input Submit
Now include updateSubmit value to validate user input.
updateSubmit: function(e){
e.preventDefault();
var user_update= this.state.user_update.trim();
if(!user_update)
{
return;
}
else
{
console.log("Send user_update value to WallUpdates component");
this.setState({ user_update: ''});
}
}
e.preventDefault();
var user_update= this.state.user_update.trim();
if(!user_update)
{
return;
}
else
{
console.log("Send user_update value to WallUpdates component");
this.setState({ user_update: ''});
}
}
Include about function at form onSubmit action.
<form onSubmit={this.updateSubmit} >
<textarea ref="updateInput" value={this.state.user_update}
onChange={this.updateChange}></textarea>
<input type='submit' value='Post' id='wallPost'/>
</form>
<textarea ref="updateInput" value={this.state.user_update}
onChange={this.updateChange}></textarea>
<input type='submit' value='Post' id='wallPost'/>
</form>
Step 2 Demo
Step 3
Back to WallFeed ComponentInclude updateAjaxSubmit for ajax operation.
var WallFeed=React.createClass({
updateAjaxSubmit: function(update)
{
var reactThis=this;
ajaxPostReact('updateFeed.php', update , reactThis, function(data){
var updates = reactThis.state.data;
var newUpdates = [data.updates[0]].concat(updates);
reactThis.setState({data: newUpdates});
});
},
render: function(){
}
});
updateAjaxSubmit: function(update)
{
var reactThis=this;
ajaxPostReact('updateFeed.php', update , reactThis, function(data){
var updates = reactThis.state.data;
var newUpdates = [data.updates[0]].concat(updates);
reactThis.setState({data: newUpdates});
});
},
render: function(){
}
});
Create an attribute onUpdateSubmit, call the updateAjaxSubmit function.
<WallForm onUpdateSubmit={this.updateAjaxSubmit}/>
updateFeed.php
JSON response for user update.
{
"updates": [
{
"user_id": "7",
"username": "rajesh",
"name": "Rajesh Tamada",
"profile_pic": "pic.png",
"update_id": "1470950004",
"user_update": "User update value",
"created": "1470950004",
"comments": []
}
]
}
"updates": [
{
"user_id": "7",
"username": "rajesh",
"name": "Rajesh Tamada",
"profile_pic": "pic.png",
"update_id": "1470950004",
"user_update": "User update value",
"created": "1470950004",
"comments": []
}
]
}
WallForm Component
Now replace console.log with onUpdateSubmit, this will set user_update data to WallUpdates component state.
updateSubmit: function(e){
e.preventDefault();
var user_update= this.state.user_update.trim();
if(!user_update)
{
return;
}
else
{
this.props.onUpdateSubmit({ user_update: user_update});
this.setState({ user_update: ''});
}
}
e.preventDefault();
var user_update= this.state.user_update.trim();
if(!user_update)
{
return;
}
else
{
this.props.onUpdateSubmit({ user_update: user_update});
this.setState({ user_update: ''});
}
}
Step 3 Demo
Step 4
textToLink.js
Create a JavaScript function for filtering HTML tags and converting text to link using regular expressions.
function textToLink(text)
{
var finalText=text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/gi;
var htmlData=finalText.replace(urlPattern, '<a target="_blank" href="$&">$&</a>');
return htmlData;
}
{
var finalText=text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/gi;
var htmlData=finalText.replace(urlPattern, '<a target="_blank" href="$&">$&</a>');
return htmlData;
}
Include this with in the HEAD tag
<script src="build/textToLink.js"></script>
Create a textToLinkHTML function in WallUpdates component.
var WallUpdates=React.createClass({
textToLinkHTML: function(content){
var finalContent=textToLink(content);
return {__html: finalContent}
},
render: function(){
var updatesEach=this.props.data.map(function(update, index)
{
return(
<div className="feedBody" key={update.created}>
<img src={update.profile_pic} className="feedImg" />
<div className="feedText">
<b>{update.name}</b>
<a href="#" className="feedDelete">X</a>
<span dangerouslySetInnerHTML={this.textToLinkHTML(update.user_update)} />
</div>
//Comments Block
</div>
)
}, this);
return(
<div id="wallFeed">
{updatesEach}
</div>
);
},
});
textToLinkHTML: function(content){
var finalContent=textToLink(content);
return {__html: finalContent}
},
render: function(){
var updatesEach=this.props.data.map(function(update, index)
{
return(
<div className="feedBody" key={update.created}>
<img src={update.profile_pic} className="feedImg" />
<div className="feedText">
<b>{update.name}</b>
<a href="#" className="feedDelete">X</a>
<span dangerouslySetInnerHTML={this.textToLinkHTML(update.user_update)} />
</div>
//Comments Block
</div>
)
}, this);
return(
<div id="wallFeed">
{updatesEach}
</div>
);
},
});
Now replace {update.user_update} in following way.
{update.user_update}
to
<span dangerouslySetInnerHTML={this.textToLinkHTML(update.user_update)} />
to
<span dangerouslySetInnerHTML={this.textToLinkHTML(update.user_update)} />
Step 4 Demo
Step 5 - Delete User Update
WallFeed Component
Create a delete update function, this will handle delete operation based on the update_id
deleteUpdate: function(e)
{
var updateIndex=e.target.getAttribute('value');
var update_id=e.target.getAttribute('data');
var data='updateID='+update_id;
var reactThis=this;
ajaxPostReact('deleteUpdate.php', data , reactThis, function(data){
reactThis.state.data.splice(updateIndex,1);
reactThis.setState({data: reactThis.state.data});
});
}
{
var updateIndex=e.target.getAttribute('value');
var update_id=e.target.getAttribute('data');
var data='updateID='+update_id;
var reactThis=this;
ajaxPostReact('deleteUpdate.php', data , reactThis, function(data){
reactThis.state.data.splice(updateIndex,1);
reactThis.setState({data: reactThis.state.data});
});
}
Create an attribute deleteUpdate and assign deleteUpdate ajax function.
<WallUpdates data={this.state.data}/>
to
<WallUpdates data={this.state.data} deleteUpdate={this.deleteUpdate}/>
to
<WallUpdates data={this.state.data} deleteUpdate={this.deleteUpdate}/>
WallUpdates Component
Assign deleteUpdate function to X hyperlink onClick
<a href="#" className="feedDelete">X</a>
to
<a href="#" className="feedDelete" value={index} data={update.update_id}
onClick={this.props.deleteUpdate} >X</a>
to
<a href="#" className="feedDelete" value={index} data={update.update_id}
onClick={this.props.deleteUpdate} >X</a>
Step 5 Demo
vinikajúce,
ReplyDeletein component wall feed method deleteUpdate
ReplyDeletee.target.value failed to work i had to change it to e.target.getAttribute('data')
Hello! Link to Part 2 doesn`t work
ReplyDeleteReplace
ReplyDeletee.target.value
to
e.target.getAttribute('value')
Perfect!!!
ReplyDeletezipped file is wrong. It downloads the angularWall.zip and contains angular.js files.
ReplyDeleteDownload link fixed.
Deletewhere can I get browser.min.js??
ReplyDeleteCheck here https://babeljs.io/
DeleteWhy you include whole jQuery library for only ajax calls? This is waste of bytes
ReplyDeleteFor cross browsing, if you want you can use vanilla js ajax function http://www.9lessons.info/2015/09/vanilla-js-browser-default-java-script.html
DeleteVery nice article. I am gonna try it now.
ReplyDeleteGood job S.Tamada, Post more on social net. and Please add some topic on online ticketing system like Service now or HPSM.
ReplyDeleteThanks
DKS
I also created a social-network with React. It's called React-Instargam-Clone-2.0.
ReplyDeleteCheck it out here: https://github.com/yTakkar/React-Instagram-Clone-2.0