All applications have 4 operations – Create, Read, Update and Delete. We call them CRUD. In this guide, we will create a “Twitter Feed” CRUD application using React, Php and Mysql.
Plan the application
This application will perform few tasks –
- Creating a new tweet (Create).
- Listing all the previous tweets (Read).
- Editing any existing tweet (Update).
- Deleting a tweet (Delete).
We need a server and database for these operations which we will create in Php and MySql.
We will create 4 php files for CRUD operations. They will act as API endpoints for our React app. Let’s say these 4 files are –
- posttweet.php – for adding new tweet.
- gettweets.php – for fetching all added tweets.
- updatetweet.php – for editing a tweet.
- deletetweet.php – for deleting a tweet.
If you are familiar with Post
and Get
requests then you must know that we send data to server using a variable. Then, server returns the response either in text or binary or JSON. We will use JSON. The request-response scheme will be like this –
Operation | Client (POST / GET) | API Endpoint | Server Response |
---|---|---|---|
CREATE | POST: {tweet: “Some tweet”} | posttweet.php | {response: “success”} or {response: “error”, result: error message} |
READ | GET | gettweets.php | {response: “success”, result: array of tweets} |
UPDATE | POST: {tweet_id: 56, tweet: “New Text”} | updatetweet.php | {response: “success”} or {response: “error”, result: error message} |
DELETE | POST: {tweet_id: 56} | deletetweet.php | {response: “success”} or {response: “error”, result: error message} |
The JSON of single tweet will be –
{
id: id of tweet,
tweet: tweet text,
time: timestamp of tweet post,
}
Building Twitter Feed UI in React
Lets create a new react project, twitterFeed.
npx create-react-app twitterFeed
cd twitterFeed
npm start
Our react app should connect with server to send and fetch tweet data. We will use Axios for it.
Let’s install Axios –
yarn add axios
We are all set to start. The first thing is to create box for posting tweets. We are breaking our UI in 2 components. First, TweetBox
which will contain the code for posting tweets. Second, TweetList
which will show the list of tweets.
import React, { useEffect, useState } from "react";
import axios from "axios";
export default function App() {
const [refreshApp, setRefreshApp] = useState(0);
const apiUrl = '' // enter url where api is hosted
return (
<div style={{ width: "400px", margin: "auto" }}>
<h2>Twitter Feed</h2>
<TweetBox />
<TweetList />
</div>
);
}
I have created refreshApp
state variable so that I can use it to refresh the app from any part of the code. Enter your api domain address in apiUrl
constant.
Code for TweetBox
component is –
const TweetBox = () => {
const [tweet, setTweet] = useState("");
const postTweet = (e) => {
e.preventDefault();
var fd = new FormData();
fd.append("tweet", tweet);
axios
.post(apiUrl + "/posttweet.php", fd)
.then(function (response) {
if (response.data.response === "success") {
setRefreshApp(refreshApp === 1 ? 0 : 1);
} else alert("Error: " + response.data.result);
})
.catch(function (error) {
console.log(error);
});
};
return (
<div
style={{
padding: "10px",
background: "#4C9BE5",
borderRadius: "5px",
boxSizing: "border-box",
overflow: "hidden"
}}
>
<form onSubmit={postTweet}>
<textarea
style={{ width: "100%" }}
onChange={(e) => setTweet(e.target.value)}
value={tweet}
></textarea>
<button
type={"submit"}
disabled={tweet.length > 0 ? false : true}
style={{ float: "right" }}
>
Post
</button>
</form>
</div>
);
};
As discussed earlier, the endpoint for CREATE is posttweet.php
. We are sending tweet text in POST variable tweet. And getting response as –
{response: 'success'}
or {response: 'error', result: error message}
The rendered output will be like this –

The next component of Twitter crud application is the TweetList
. Let’s design that. We will have multiple operations here.
This will be the code for displaying tweet list –
const TweetList = () => {
const [tweets, setTweets] = useState([]);
useEffect(() => {
axios
.get(apiUrl + "/gettweets.php")
.then(function (response) {
if (response.data.response === "success") {
setTweets(response.data.result);
}
})
.catch(function (error) {
console.log(error);
});
});
const SingleTweet = (props) => {
const [isEditing, setIsEditing] = useState(0);
const [newtweet, setNewtweet] = useState(props.info.tweet);
return (
<div
style={{
padding: "10px",
marginBottom: "10px",
background: "#eee",
overflow: "hidden"
}}
>
{isEditing === 1 ? (
<div>
<form onSubmit={(e) => editTweet(e, props.info.id, newtweet)}>
<textarea
style={{ width: "100%" }}
onChange={(e) => setNewtweet(e.target.value)}
value={newtweet}
></textarea>
<button
type={"submit"}
disabled={newtweet.length > 0 ? false : true}
style={{ float: "right" }}
>
Update
</button>
</form>
</div>
) : (
<div>
<span style={{ color: "blue", fontWeight: "bold" }}>@User</span>
{props.info.tweet}
<div>
<a
href="#"
onClick={(e) => {
e.preventDefault();
setIsEditing(1);
}}
>
Edit
</a>
<a href="#" onClick={(e) => deleteTweet(e, props.info.id)}>
Delete
</a>
<span style={{ float: "right" }}>
{new Date(props.info.time * 1000).toLocaleString()}
</span>
</div>
</div>
)}
</div>
);
};
return (
<div style={{ marginTop: "10px" }}>
{tweets.map((tweet) => (
<SingleTweet key={tweet.id + "_" + tweet.time} info={tweet} />
))}
</div>
);
};
We are getting all the tweets using gettweets.php
endpoint. The rendered list will look like this –

Let’s create code for editing the tweets –
const editTweet = (e, tweet_id, newtweet) => {
e.preventDefault();
var fd = new FormData();
fd.append("tweet", newtweet);
fd.append("tweet_id", tweet_id);
axios
.post(apiUrl + "/updatetweet.php", fd)
.then(function (response) {
if (response.data.response === "success") {
setRefreshApp(refreshApp === 1 ? 0 : 1);
} else alert("Error: " + response.data.result);
})
.catch(function (error) {
console.log(error);
});
};
Code for deleting the tweets –
const deleteTweet = (e, tweet_id) => {
e.preventDefault();
var fd = new FormData();
fd.append("tweet_id", tweet_id);
axios
.post(apiUrl + "/deletetweet.php", fd)
.then(function (response) {
if (response.data.response === "success") {
setRefreshApp(refreshApp === 1 ? 0 : 1);
} else alert("Error: " + response.data.result);
})
.catch(function (error) {
console.log(error);
});
};
Let’s now compile all the functions and components. Open App.js
file and replace its content with this code –
import React, { useEffect, useState } from "react";
import axios from "axios";
export default function App() {
const [refreshApp, setRefreshApp] = useState(0);
const apiUrl = '' // enter url where api is hosted
const TweetBox = () => {
const [tweet, setTweet] = useState("");
const postTweet = (e) => {
e.preventDefault();
var fd = new FormData();
fd.append("tweet", tweet);
axios
.post(apiUrl + "/posttweet.php", fd)
.then(function (response) {
if (response.data.response === "success") {
setRefreshApp(refreshApp === 1 ? 0 : 1);
} else alert("Error: " + response.data.result);
})
.catch(function (error) {
console.log(error);
});
};
return (
<div
style={{
padding: "10px",
background: "#4C9BE5",
borderRadius: "5px",
boxSizing: "border-box",
overflow: "hidden"
}}
>
<form onSubmit={postTweet}>
<textarea
style={{ width: "100%" }}
onChange={(e) => setTweet(e.target.value)}
value={tweet}
></textarea>
<button
type={"submit"}
disabled={tweet.length > 0 ? false : true}
style={{ float: "right" }}
>
Post
</button>
</form>
</div>
);
};
const TweetList = () => {
const [tweets, setTweets] = useState([]);
useEffect(() => {
axios
.get(apiUrl + "/gettweets.php")
.then(function (response) {
if (response.data.response === "success") {
setTweets(response.data.result);
}
})
.catch(function (error) {
console.log(error);
});
});
const editTweet = (e, tweet_id, newtweet) => {
e.preventDefault();
var fd = new FormData();
fd.append("tweet", newtweet);
fd.append("tweet_id", tweet_id);
axios
.post(apiUrl + "/updatetweet.php", fd)
.then(function (response) {
if (response.data.response === "success") {
setRefreshApp(refreshApp === 1 ? 0 : 1);
} else alert("Error: " + response.data.result);
})
.catch(function (error) {
console.log(error);
});
};
const deleteTweet = (e, tweet_id) => {
e.preventDefault();
var fd = new FormData();
fd.append("tweet_id", tweet_id);
axios
.post(apiUrl + "/deletetweet.php", fd)
.then(function (response) {
if (response.data.response === "success") {
setRefreshApp(refreshApp === 1 ? 0 : 1);
} else alert("Error: " + response.data.result);
})
.catch(function (error) {
console.log(error);
});
};
const SingleTweet = (props) => {
const [isEditing, setIsEditing] = useState(0);
const [newtweet, setNewtweet] = useState(props.info.tweet);
return (
<div
style={{
padding: "10px",
marginBottom: "10px",
background: "#eee",
overflow: "hidden"
}}
>
{isEditing === 1 ? (
<div>
<form onSubmit={(e) => editTweet(e, props.info.id, newtweet)}>
<textarea
style={{ width: "100%" }}
onChange={(e) => setNewtweet(e.target.value)}
value={newtweet}
></textarea>
<button
type={"submit"}
disabled={newtweet.length > 0 ? false : true}
style={{ float: "right" }}
>
Update
</button>
</form>
</div>
) : (
<div>
<span style={{ color: "blue", fontWeight: "bold" }}>@User</span>
{props.info.tweet}
<div>
<a
href="#"
onClick={(e) => {
e.preventDefault();
setIsEditing(1);
}}
>
Edit
</a>
<a href="#" onClick={(e) => deleteTweet(e, props.info.id)}>
Delete
</a>
<span style={{ float: "right" }}>
{new Date(props.info.time * 1000).toLocaleString()}
</span>
</div>
</div>
)}
</div>
);
};
return (
<div style={{ marginTop: "10px" }}>
{tweets.map((tweet) => (
<SingleTweet key={tweet.id + "_" + tweet.time} info={tweet} />
))}
</div>
);
};
return (
<div style={{ width: "400px", margin: "auto" }}>
<h2>Twitter Feed</h2>
<TweetBox />
<TweetList />
</div>
);
}
Creating Twitter CRUD database in MySql
For our application we just need a single table. Let’s call it “twitterfeed“. It will have a primary key, a text field for tweets and a timestamp to record tweet posting or updating time.
CREATE TABLE twitterfeed (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
tweet VARCHAR(250) NOT NULL,
post_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
Creating API Endpoints in Php
First of all we need to create a file to establish database connection. This file could be included in any other php script to access queries. Let’s call it mysql.inc.php
.
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Content-Type");
$dbc = @mysqli_connect('localhost', REPLACE_WITH_DATABASE_USERNAME, REPLACE_WITH_DATABASE_PASSWORD, REPLACE_WITH_DATABASE_NAME);
mysqli_set_charset($dbc, 'utf8');
function mysql_safe($data)
{
global $dbc;
return mysqli_real_escape_string($dbc, $data);
}
Next we will create files for our CRUD operations. We will start with reading tweets. In our whole application we have called this file as gettweets.php
.
<?php
require('mysql.inc.php');
$query = mysqli_query($dbc, "SELECT id, tweet, UNIX_TIMESTAMP(post_timestamp) AS post_timestamp FROM twitterfeed ORDER BY id DESC LIMIT 25");
$tweets = array();
while($query && $result=mysqli_fetch_array($query, MYSQLI_ASSOC)){
array_push($tweets, array('id'=>$result['id'], 'tweet'=>$result['tweet'], 'time'=>$result['post_timestamp']));
}
echo json_encode(array('response' => 'success', 'result' => $tweets));
For this file –
POST / GET – none
Response – JSON(
{
"response" : "success",
"result" : [
{
"id" : INT(tweet id),
"tweet" : STRING("tweet text"),
"time" : TIMESTAMP,
},
...
]
}
)
Endpoint for posting tweets is posttweet.php
. It will accept a POST request of tweet text.
<?php
require('mysql.inc.php');
if(isset($_POST['tweet'])){
if(mb_strlen(trim($_POST['tweet'])) > 0){
$query = mysqli_query($dbc, "INSERT INTO twitterfeed(tweet) VALUES('".mysql_safe(trim($_POST['tweet']))."')");
if(mysqli_affected_rows($dbc) > 0)
echo json_encode(array('response' => 'success'));
else
echo json_encode(array('response' => 'error', 'result' => 'Could not save your tweet'));
} else {
echo json_encode(array('response' => 'error', 'result' => 'Please write something before posting'));
}
} else {
echo json_encode(array('response' => 'error', 'result' => 'Invalid Activity'));
}
POST – {"tweet" : "tweet text"}
Response – JSON(
{
"response" : "success" | "error",
"result" : "Could not save your tweet" | "Please write something before posting" | "Invalid Activity"
}
)
Text of the tweets could be updated using updatetweet.php
. Here is the code –
<?php
require('mysql.inc.php');
if(isset($_POST['tweet_id']) && isset($_POST['tweet'])){
if(is_numeric($_POST['tweet_id']) && mb_strlen(trim($_POST['tweet'])) > 0){
$query = mysqli_query($dbc, "UPDATE twitterfeed SET tweet = '".mysql_safe(trim($_POST['tweet']))."' WHERE id=".mysql_safe($_POST['tweet_id']));
if(mysqli_affected_rows($dbc) > 0)
echo json_encode(array('response' => 'success'));
else
echo json_encode(array('response' => 'error', 'result' => 'Could not update your tweet'));
} else {
echo json_encode(array('response' => 'error', 'result' => 'Invalid Activity'));
}
} else {
echo json_encode(array('response' => 'error', 'result' => 'Invalid Activity'));
}
POST –
{
"tweet_id" : INT(id of tweet to be updated),
"tweet" : STRING("updated tweet text"),
}
Response – JSON(
{
"response" : "success" | "error",
"result" : "Could not update your tweet" | "Invalid Activity"
}
)
Last but not the least, deletion, could be done by deletetweet.php
. We will send the id of tweet which is to be deleted.
<?php
require('mysql.inc.php');
if(isset($_POST['tweet_id'])){
if(is_numeric($_POST['tweet_id'])){
$query = mysqli_query($dbc, "DELETE FROM twitterfeed WHERE id=".mysql_safe($_POST['tweet_id']));
if(mysqli_affected_rows($dbc) > 0)
echo json_encode(array('response' => 'success'));
else
echo json_encode(array('response' => 'error', 'result' => 'Could not delete your tweet'));
} else {
echo json_encode(array('response' => 'error', 'result' => 'Invalid Activity'));
}
} else {
echo json_encode(array('response' => 'error', 'result' => 'Invalid Activity'));
}
POST – { "tweet_id" : id of tweed to be deleted}
Response – JSON(
{
"response" : "success" | "error",
"result" : "Could not delete your tweet" | "Invalid Activity"
}
)
I learned CRUD in 10 Minutes.
Click to Tweet this
Live Demo of Twitter CRUD application
You may also like –
Comments