React CRUD Tutorial – JavaScript Programming – Step By Step Guide!


Previously, we learned our jQuery AJAX CRUD tutorial. Today we will learn how to create or insert, read, update, and delete database records with React.

Our tutorial for today will cover the following contents:

1.0 Program Output
2.0 React: What, Why, Who and Think
3.0 Technologies Used In This Tutorial
4.0 Set Up The REST API

5.0 Basic Files & Folders
5.1 File Structure
5.2 Create index.html file
5.3 Create custom CSS file
5.4 Create main.component.js file
5.5 Create “products” scripts
5.5 Output

6.0 How To Read JSON Data Using React?
6.1 Create “Read Products” Component
6.2 Create “Top Actions” Component
6.3 Create “ProductsTable” component
6.4 Create “ProductRow” component
6.5 Output

7.0 How To Create or Insert Data Using React?
7.1 Create “CreateProductComponent” Class
7.2 Initialize component state
7.3 Handle form field changes
7.4 Handle “Save” button
7.5 Render “Create Product” HTML Form
7.6 Output

8.0 How To Read One Data Using React?
8.1 Create “ReadOneProductComponent” Class
8.2 Initialize component state
8.3 Render Component HTML
8.4 Output

9.0 How To Update Data Using React?
9.1 Create “UpdateProductComponent” Class
9.2 Initialize component state
9.3 Handle form field changes
9.4 Handle “Save Changes” button
9.5 Render “Update Product” HTML Form
9.6 Output

10.0 How To Delete Data Using React?
10.1 Create “DeleteProductComponent” Class
10.2 Change Page Title
10.3 Handle “Yes” Button
10.4 Render “Delete Confirmation” Box
10.5 Output

11.0 How To Run The Source Code?
12.0 Download LEVEL 1 Source Code
13.0 Download LEVEL 2 Source Code
14.0 Download ALL LEVELS

15.0 What’s Next?
16.0 Related Source Codes
17.0 Online Resources
18.0 Some Notes

1.0 Program Output

Below are some screenshots of our tutorial’s output. You can click an image to view the larger version of it. Use the left and right arrow to navigate through the screenshots.

1.1 LEVEL 1 Source Code Output


1.2 LEVEL 2 Source Code Output


The LEVEL 2 source code output proves that you can add and customize more features. It’s easier and faster if you will learn by following our tutorial below.

Downloading our source codes is your huge advantage as well. For now, let’s proceed to the step by step tutorial of our LEVEL 1 source code. Enjoy!

2.0 React: What, Why, Who and Think

2.1 What is React?

React is a JavaScript library for building user interfaces. It is maintained by Facebook, Instagram and a community of individual developers and corporations.

2.2 Why use React?

Using React allows you to simply express how your app should look at any given point in time. React will automatically manage all UI updates when your underlying data changes. When the data changes, React conceptually hits the “refresh” button, and knows to only update the changed parts.

2.3 Who uses React?

Aside from Facebook and Instagram, many well-known companies uses React including: Dropbox, PayPal, Nextflix, Khan Academy, Airbnb, Alipay, Asana and many more.

2.4 Thinking in React

It is very important that we understand the thought process of building web apps with React. Here’s a start: We start with a mock. Then, we break the UI into a component or parts of the UI. In the following image, you can see the mock and components in colored boxes.

thinking-in-react-components

I will not discuss this topic longer here. To learn more about how to think in React, click here.

Another point: Before, we code HTML and JavaScript separately on a web page. In React, we code HTML inside JavaScript. This is made possible through JSX. To learn more about JSX, click here.

React concepts can be hard to grasp at first, but you will get there. If you do actual coding with React, you will understand it better and faster. This is why our step-by-step React CRUD tutorial below will be very useful.

3.0 Technologies Used In This Tutorial

Here we will learn how to create, read update and delete database records – CRUD operations with PHP, MySQL, React, Babel, jQuery and Bootstrap.

Why do I use these technologies for this React CRUD tutorial? Here are my reasons:

  1. They work.
  2. Most audience of our blog are very familiar with these technologies.
  3. The goal of this tutorial is for you to learn how to use React.
  4. React is only the V in MVC.
  5. React don’t make assumptions about the rest of your technology stack.

Now, let’s take a look at the roles of each technology that we will use:

  • PHP – will handle server side script.
  • MySQL – will store our data.
  • React – will make our UI fast and interactive.
  • Babel – will compile our JavaScript so we don’t have to wait for browser support.
  • jQuery – will do AJAX requests. React official docs shows jQuery examples.
  • Bootstrap – will make our UI look better.

For those who ask, React can work with AngularJS. In short, it can work with the MEAN (mongoDB, Express, AngularJS and NodeJS) framework. We will have another tutorial for that soon! Please subscribe so I can notify you when it is done.

4.0 Set Up The REST API

In this tutorial, we are going to use a REST API built with PHP.

We did not include REST API source code in this page because we want you to focus on learning how to code with React, not PHP.

But the good news is, we made a separate tutorial about how to build a simple REST API with PHP. Click here to learn the step-by-step PHP REST API tutorial.

I highly recommend learning our REST API tutorial first. This is because we are going to use that API for the rest of this tutorial.

But if you already have your own REST API that will work with this tutorial, that’s okay as well.

In my case, one example where I can access the REST API is: http://localhost/api/product/read.php

That link will show me the list of products from the database, in JSON format. It looks like the following screenshot.

The data above will be consumed by our React app. The list of products will be displayed in Bootstrap table with buttons like “Read One”, “Update” and “Delete”. You will see it in the “How To Read JSON Data Using React?” section of this tutorial.

By the way, I’m using a Chrome extension called JSONView to make the JSON data readable in the browser.

5.0 Basic Files & Folders

5.1 File Structure

Our LEVEL 1 source code will have the following files and folders.

├─app/
├───assets/
├──────css/
├─────────custom.css
├───product/
├──────create_product.component.js
├──────delete_product.component.js
├──────product_table_row.component.js
├──────product_table.component.js
├──────read_one_product.component.js
├──────read_products.component.js
├──────top_actions.component.js
├──────update_product.component.js
├───main.component.js
├─index.html

The functions of each files above were explained in different sections of this tutorial.

5.2 Create index.html file

The index.html is the first file that will run on our browser. It contains our:

  • Bootstrap CSS – to make our web app look better.
  • Custom CSS – Bootstrap CSS cannot do it all so we need this custom styles.
  • Container DIV tag – our React application will be injected in this DIV tag.
  • React libraries – JavaScript files needed to run a React web application.
  • React custom codes – main custom codes of our React web application
  • jQuery library – will be used for AJAX requests. It is required by Bootstrap JavaScript as well.
  • Bootstrap JavaScript – needed to make use of more Bootstrap features like drop-down menu, etc.

Create index.html and put the following code.

<!DOCTYPE html>
<html lang="en">
<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>LEVEL 1 - React CRUD Tutorial - codeofaninja.com</title>

    <!-- Bootstrap CSS -->
	<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" media="screen" />

    <!-- Custom CSS -->
	<link href="app/assets/css/custom.css" rel="stylesheet" media="screen" />

</head>
<body>

    <!-- container -->
    <div class="container">

        <div class="page-header">
            <h1>Loading...</h1>
        </div>

        <!-- placeholder for rendering react components -->
        <div id='content'></div>

    </div>
	<!-- /container -->

<!-- react js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>

<!-- react code -->
<script type="text/babel" src="app/product/update_product.component.js"></script>
<script type="text/babel" src="app/product/create_product.component.js"></script>
<script type="text/babel" src="app/product/read_one_product.component.js"></script>
<script type="text/babel" src="app/product/delete_product.component.js"></script>
<script type="text/babel" src="app/product/product_table_row.component.js"></script>
<script type="text/babel" src="app/product/product_table.component.js"></script>
<script type="text/babel" src="app/product/top_actions.component.js"></script>
<script type="text/babel" src="app/product/read_products.component.js"></script>
<script type="text/babel" src="app/main.component.js"></script>

<!-- jQuery library required by bootsrap js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<!-- bootstrap JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</body>
</html>

5.3 Create custom CSS file

As said earlier, Bootstrap CSS cannot do it all so we need this custom styles.

  • Create “app” folder.
  • Create “assets” folder inside “app” folder.
  • Create “css” folder inside “assets” folder.
  • Create “custom.css” file inside “css” folder.
  • Open “custom.css” file and put the following code.
.text-align-center{ text-align:center; }
.margin-zero{ margin:0; }
.overflow-hidden{ overflow:hidden; }
.margin-bottom-1em{ margin-bottom:1em; }
.m-r-1em{ margin-right:1em; }

5.4 Create main.component.js file

Our “main component” will hold all other components of our react application.

Open “app” folder. Create “main.component.js” file. Put the following code.

// component that decides which main component to load: read or create/update
var MainApp = React.createClass({

	// initial mode is 'read' mode
    getInitialState: function(){
        return {
            currentMode: 'read',
            productId: null
        };
    },

	// used when use clicks something that changes the current mode
    changeAppMode: function(newMode, productId){
        this.setState({currentMode: newMode});
            if(productId !== undefined){
            this.setState({productId: productId});
        }
    },

	// render the component based on current or selected mode
    render: function(){

        var modeComponent =
            <ReadProductsComponent
            changeAppMode={this.changeAppMode} />;

        switch(this.state.currentMode){
            case 'read':
                break;
            case 'readOne':
                modeComponent = <ReadOneProductComponent productId={this.state.productId} changeAppMode={this.changeAppMode}/>;
                break;
            case 'create':
                modeComponent = <CreateProductComponent changeAppMode={this.changeAppMode}/>;
                break;
            case 'update':
                modeComponent = <UpdateProductComponent productId={this.state.productId} changeAppMode={this.changeAppMode}/>;
                break;
            case 'delete':
                modeComponent = <DeleteProductComponent productId={this.state.productId} changeAppMode={this.changeAppMode}/>;
                break;
            default:
                break;
        }

        return modeComponent;
    }
});

// go and render the whole React component on to the div with id 'content'
ReactDOM.render(
    <MainApp />,
    document.getElementById('content')
);

5.5 Create “products” scripts

We need several JavaScript files that contains React code to make our application work.

Open “app” folder. Create “product” folder inside “app” folder.

Create the following JavaScript files.

  • update_product.component.js
  • create_product.component.js
  • read_one_product.component.js
  • delete_product.component.js
  • product_table_row.component.js
  • product_table.component.js
  • top_actions.component.js
  • read_products.component.js

Currently, those JavaScript files are empty. Where are the codes?

We will see the codes on the next several sections of this tutorial.

5.6 Output

Since our JavaScript files are empty, the output of all we did above is a blank page.

See it for yourself by running http://localhost/react-crud-level-1/index.html on your browser.

6.0 How To Read JSON Data Using React?

6.1 Create “Read Products” Component

This component will hold the product records using an HTML table. It will hold the “create product” button as well. The button or “top actions” are located on the upper right corner of this component.

Open “app” folder.
Open “products” folder inside “app” folder.
Open “read_products.component.js” file.
Put the following code in it and save it.

// component that contains all the logic and other smaller components
// that form the Read Products view
window.ReadProductsComponent = React.createClass({
    getInitialState: function() {
        return {
            products: []
        };
    },

    // on mount, fetch all products and stored them as this component's state
    componentDidMount: function() {

        this.serverRequest = $.get("http://localhost/api/product/read.php", function (products) {
            this.setState({
                products: products.records
            });
        }.bind(this));
    },

    // on unmount, kill product fetching in case the request is still pending
    componentWillUnmount: function() {
        this.serverRequest.abort();
    },

    // render component on the page
    render: function() {
        // list of products
        var filteredProducts = this.state.products;
        $('.page-header h1').text('Read Products');

        return (
            <div className='overflow-hidden'>
                <TopActionsComponent changeAppMode={this.props.changeAppMode} />

                <ProductsTable
                    products={filteredProducts}
                    changeAppMode={this.props.changeAppMode} />
            </div>
        );
    }
});

6.2 Create “Top Actions” Component

The previous section makes use of “TopActionsComponent”. This component holds our “create product” button. You can add more buttons in this component. For now, we have only one.

Still in the “product” folder. Open “top_actions.component.js” file.
Put the following code in it and save it.

// component that contains the functionalities that appear on top of
// the products table: create product
window.TopActionsComponent = React.createClass({
    render: function(){
        return (
            <div>
                <a href='#'
                    onClick={() => this.props.changeAppMode('create')}
                    className='btn btn-primary margin-bottom-1em'> Create product
                </a>
            </div>
        );
    }
});

6.3 Create “ProductsTable” Component

We previously made use of “ProductsTable” component as well. This will hold the table header and table rows with products data.

Still in the “product” folder. Open “product_table.component.js” file.
Put the following code in it and save it.

// component for the whole products table
window.ProductsTable = React.createClass({
    render: function() {

    var rows = this.props.products
        .map(function(product, i) {
            return (
                <ProductRow
                    key={i}
                    product={product}
                    changeAppMode={this.props.changeAppMode} />
            );
        }.bind(this));

        return(
            !rows.length
                ? <div className='alert alert-danger'>No products found.</div>
                :
                <table className='table table-bordered table-hover'>
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Description</th>
                            <th>Price</th>
                            <th>Category</th>
                            <th>Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        {rows}
                    </tbody>
                </table>
        );
    }
});

6.4 Create “ProductRow” Component

On the previous section, we used the “ProductRow” component. This component will hold a table row with product data. It will hold three buttons as well. The “Read One”, “Edit” and “Delete” product button.

Still in the “product” folder. Open “product_table_row.component.js” file.
Put the following code in it and save it.

// component that renders a single product
window.ProductRow = React.createClass({
    render: function() {
    return (
        <tr>
            <td>{this.props.product.name}</td>
            <td>{this.props.product.description}</td>
            <td>${parseFloat(this.props.product.price).toFixed(2)}</td>
            <td>{this.props.product.category_name}</td>
            <td>
                <a href='#'
                    onClick={() => this.props.changeAppMode('readOne', this.props.product.id)}
                    className='btn btn-info m-r-1em'> Read One
                </a>
                <a href='#'
                    onClick={() => this.props.changeAppMode('update', this.props.product.id)}
                    className='btn btn-primary m-r-1em'> Edit
                </a>
                <a
                    onClick={() => this.props.changeAppMode('delete', this.props.product.id)}
                    className='btn btn-danger'> Delete
                </a>
            </td>
        </tr>
        );
    }
});

6.5 Output

If we completed the steps above, the output should be an HTML table with product data on each table row. The “Read One”, “Edit” and “Delete” buttons should be seen on each table row as well.

7.0 How To Create or Insert Data Using React?

7.1 Create “CreateProductComponent” Class

The “CreateProductComponent” class will contain the logic and HTML of our app’s “Create Product” feature.

window.CreateProductComponent = React.createClass({
	// initial component states will be here
});

7.2 Initialize component state

We need to initialize states for this component. Usually, initial states are empty as seen in the getInitialState method.

When component was mounted, we will get the list of categories from the API. The returned categories will be used in the form’s “categories” dropdown field.

When component was unmounted, we need to stop the server request, just in case the request is still pending.

Replace “// initial component states will be here” of the previous section with the following code.

// initialize values
getInitialState: function() {
	return {
		categories: [],
		selectedCategoryId: -1,
		name: '',
		description: '',
		price: '',
		successCreation: null
	};
},

// on mount, get all categories and store them in this component's state
componentDidMount: function() {
	this.serverRequest = $.get("http://localhost/api/category/read.php", function (categories) {
		this.setState({
			categories: categories.records
		});
	}.bind(this));

	$('.page-header h1').text('Create product');
},

// on unmount, stop getting categories in case the request is still loading
componentWillUnmount: function() {
	this.serverRequest.abort();
},

// handle form field changes here

7.3 Handle form field changes

We need methods to keep track of change on our form fields. As user types or changes a field’s value, it is saved to the component’s state.

Replace “// handle form field changes here” of the previous section with the following code.

// handle category change
onCategoryChange: function(e) {
	this.setState({selectedCategoryId: e.target.value});
},

// handle name change
onNameChange: function(e) {
	this.setState({name: e.target.value});
},

// handle description change
onDescriptionChange: function(e) {
	this.setState({description: e.target.value});
},

// handle price change
onPriceChange: function(e) {
	this.setState({price: e.target.value});
},

// handle save button here

7.4 Handle “Save” button

When user clicks the “save” button, form data must be sent to the API. This way, data will be saved on the database.

We need the “onSave” method to handle this event.

Replace “// handle save button here” of the previous section with the following code.

// handle save button clicked
onSave: function(e){

	// data in the form
	var form_data={
		name: this.state.name,
		description: this.state.description,
		price: this.state.price,
		category_id: this.state.selectedCategoryId
	};

	// submit form data to api
	$.ajax({
		url: "http://localhost/api/product/create.php",
		type : "POST",
		contentType : 'application/json',
		data : JSON.stringify(form_data),
		success : function(response) {

			// api message
			this.setState({successCreation: response['message']});

			// empty form
			this.setState({name: ""});
			this.setState({description: ""});
			this.setState({price: ""});
			this.setState({selectedCategoryId: -1});

		}.bind(this),
		error: function(xhr, resp, text){
			// show error to console
			console.log(xhr, resp, text);
		}
	});

	e.preventDefault();
},

// render component here

7.5 Render “Create Product” HTML Form

Now you’re asking: Where’s the HTML form?

Our HTML form is in the “render” method.

Replace “// render component here” of the previous section with the following code.

render: function() {

    // make categories as option for the select tag.
    var categoriesOptions = this.state.categories.map(function(category){
        return (
            <option key={category.id} value={category.id}>{category.name}</option>
        );
    });

    /*
    - tell the user if a product was created
    - tell the user if unable to create product
    - button to go back to products list
    - form to create a product
    */
    return (
    <div>
        {

            this.state.successCreation == "Product was created." ?
                <div className='alert alert-success'>
                    Product was saved.
                </div>
            : null
        }

        {

            this.state.successCreation == "Unable to create product." ?
                <div className='alert alert-danger'>
                    Unable to save product. Please try again.
                </div>
            : null
        }

        <a href='#'
            onClick={() => this.props.changeAppMode('read')}
            className='btn btn-primary margin-bottom-1em'> Read Products
        </a>


        <form onSubmit={this.onSave}>
            <table className='table table-bordered table-hover'>
            <tbody>
                <tr>
                    <td>Name</td>
                    <td>
                        <input
                        type='text'
                        className='form-control'
                        value={this.state.name}
                        required
                        onChange={this.onNameChange} />
                    </td>
                </tr>

                <tr>
                    <td>Description</td>
                    <td>
                        <textarea
                        type='text'
                        className='form-control'
                        required
                        value={this.state.description}
                        onChange={this.onDescriptionChange}>
                        </textarea>
                    </td>
                </tr>

                <tr>
                    <td>Price ($)</td>
                    <td>
                        <input
                        type='number'
                        step="0.01"
                        className='form-control'
                        value={this.state.price}
                        required
                        onChange={this.onPriceChange}/>
                    </td>
                </tr>

                <tr>
                    <td>Category</td>
                    <td>
                        <select
                        onChange={this.onCategoryChange}
                        className='form-control'
                        value={this.state.selectedCategoryId}>
                        <option value="-1">Select category...</option>
                        {categoriesOptions}
                        </select>
                    </td>
                </tr>

                <tr>
                    <td></td>
                    <td>
                        <button
                        className='btn btn-primary'
                        onClick={this.onSave}>Save</button>
                    </td>
                </tr>
                </tbody>
            </table>
        </form>
    </div>
    );
}

7.6 Output

When you click the “Create Product” button, output that you should see is an HTML form with fields: Name, description, price and category drop-down list. A “Save” button should be seen as well.

Try to fill-out the form and click the “Save” button. Click the “Read Products” button and see if your record is in the list. If it’s there, it means our React app is working.

8.0 How To Read One Data Using React?

8.1 Create “ReadOneProductComponent” Class

The “ReadOneProductComponent” class will contain the logic and HTML of our app’s “Read One Product” feature.

// component that contains the logic to read one product
window.ReadOneProductComponent = React.createClass({
	// initial component state will be here
});

8.2 Initialize component state

Initial states are empty as seen in the getInitialState method.

When component was mounted, we will get the product data from the API. The returned data will be set to component state. The state’s value will be used in HTML table.

When component was unmounted, we need to stop the server request, just in case the request is still pending.

Replace “// initial component state will be here” of the previous section with the following code.

getInitialState: function() {
    // Get this product fields from the data attributes we set on the
    // #content div, using jQuery
    return {
        id: 0,
        name: '',
        description: '',
        price: 0,
        category_name: ''
    };
},

// on mount, read product data and them as this component's state
componentDidMount: function(){

    var productId = this.props.productId;

    this.serverRequestProd = $.get("http://localhost/api/product/read_one.php?id=" + productId,
        function (product) {
            this.setState({category_name: product.category_name});
            this.setState({id: product.id});
            this.setState({name: product.name});
            this.setState({description: product.description});
            this.setState({price: product.price});
        }.bind(this));

    $('.page-header h1').text('Read Product');
},

// on unmount, kill categories fetching in case the request is still pending
componentWillUnmount: function() {
    this.serverRequestProd.abort();
},

// render component html will be here

8.3 Render Component HTML

We will use the “render” method again to render this “ReadOneProductComponent” HTML on the web page.

Replace “// render component html will be here” of the previous section with the following code.

render: function() {

    return (
        <div>
            <a href='#'
                onClick={() => this.props.changeAppMode('read')}
                className='btn btn-primary margin-bottom-1em'>
                Read Products
            </a>

            <form onSubmit={this.onSave}>
                <table className='table table-bordered table-hover'>
                    <tbody>
                    <tr>
                        <td>Name</td>
                        <td>{this.state.name}</td>
                    </tr>

                    <tr>
                        <td>Description</td>
                        <td>{this.state.description}</td>
                    </tr>

                    <tr>
                        <td>Price ($)</td>
                        <td>${parseFloat(this.state.price).toFixed(2)}</td>
                    </tr>

                    <tr>
                        <td>Category</td>
                        <td>{this.state.category_name}</td>
                    </tr>

                    </tbody>
                </table>
            </form>
        </div>
    );
}

8.4 Output

When you click the “Read One” button, you should see an HTML table with a product’s data. The “Read Products” button should be seen as well.

9.0 How To Update Data Using React?

9.1 Create “UpdateProductComponent” Class

The “UpdateProductComponent” class will contain the logic and HTML of our app’s “Update Product” feature.

// component that contains the logic to update a product
window.UpdateProductComponent = React.createClass({
	// initial component states will be here
});

9.2 Initialize component state

Initial component states are empty as seen in the getInitialState method.

When component was mounted, we will get the list of categories from the API. The returned categories will be used in the form’s “categories” dropdown field. We get a product data based on given product ID as well. This will fill out the “update product” form.

When component was unmounted, we need to stop both server requests, just in case any of the request is still pending.

Replace “// initial component states will be here” of the previous section with the following code.

getInitialState: function() {
    // Get this product fields from the data attributes we set on the
    // #content div, using jQuery
    return {
        categories: [],
        selectedCategoryId: 0,
        id: 0,
        name: '',
        description: '',
        price: 0,
        successUpdate: null
    };
},

// on mount, fetch all categories and one product data to stored them as this component's state
componentDidMount: function(){

	// read categories
    this.serverRequestCat = $.get("http://localhost/api/category/read.php",
        function (categories) {
            this.setState({
                categories: categories.records
            });
        }.bind(this));

	// read one product data
    var productId = this.props.productId;
    this.serverRequestProd = $.get("http://localhost/api/product/read_one.php?id=" + productId,
        function (product) {
            this.setState({selectedCategoryId: product.category_id});
            this.setState({id: product.id});
            this.setState({name: product.name});
            this.setState({description: product.description});
            this.setState({price: product.price});
        }.bind(this));

    $('.page-header h1').text('Update product');
},

// on unmount, kill categories fetching in case the request is still pending
componentWillUnmount: function() {
    this.serverRequestCat.abort();
    this.serverRequestProd.abort();
},

// handle form field changes here

9.3 Handle form field changes

We need methods to keep track of any input changes on our form fields. As user types or changes a field’s value, it is saved to the component’s state.

Replace “// handle form field changes here” of the previous section with the following code.

// handle category change
onCategoryChange: function(e){
    this.setState({selectedCategoryId: e.target.value});
},

// handle name change
onNameChange: function(e){
    this.setState({name: e.target.value});
},

// handle description change
onDescriptionChange: function(e){
    this.setState({description: e.target.value});
},

// handle price change
onPriceChange: function(e){
    this.setState({price: e.target.value});
},

// handle save changes button here

9.4 Handle “Save Changes” button

When user clicks the “Save Changes” button, form data must be sent to the API. The updated data will be saved on the database.

We will create the “onSave” method to handle this event.

Replace “// handle save changes button here” of the previous section with the following code.

// handle save changes button clicked
onSave: function(e){

    // data in the form
    var form_data={
        id: this.state.id,
        name: this.state.name,
        description: this.state.description,
        price: this.state.price,
        category_id: this.state.selectedCategoryId
    };

    // submit form data to api
    $.ajax({
        url: "http://localhost/api/product/update.php",
        type : "POST",
        contentType : 'application/json',
        data : JSON.stringify(form_data),
        success : function(response) {
            this.setState({successUpdate: response['message']});
        }.bind(this),
        error: function(xhr, resp, text){
            // show error to console
            console.log(xhr, resp, text);
        }
    });

    e.preventDefault();
},

// render component here

9.5 Render “Update Product” HTML Form

Now you’re asking: Where’s the HTML form filled-out with product data?

Our HTML form is in the “render” method below.

Replace “// render component here” of the previous section with the following code.

render: function() {
    var categoriesOptions = this.state.categories.map(function(category){
        return (
            <option key={category.id} value={category.id}>{category.name}</option>
        );
    });

    return (
        <div>
            {
                this.state.successUpdate == "Product was updated." ?
                    <div className='alert alert-success'>
                        Product was updated.
                    </div>
                : null
            }

            {
                this.state.successUpdate == "Unable to update product." ?
                    <div className='alert alert-danger'>
                        Unable to update product. Please try again.
                    </div>
                : null
            }

            <a href='#'
                onClick={() => this.props.changeAppMode('read')}
                className='btn btn-primary margin-bottom-1em'>
                Read Products
            </a>

            <form onSubmit={this.onSave}>
                <table className='table table-bordered table-hover'>
                    <tbody>
                    <tr>
                        <td>Name</td>
                        <td>
                            <input
                                type='text'
                                className='form-control'
                                value={this.state.name}
                                required
                                onChange={this.onNameChange} />
                        </td>
                    </tr>

                    <tr>
                        <td>Description</td>
                        <td>
                            <textarea
                                type='text'
                                className='form-control'
                                required
                                value={this.state.description}
                                onChange={this.onDescriptionChange}></textarea>
                        </td>
                    </tr>

                    <tr>
                        <td>Price ($)</td>
                        <td>
                            <input
                                type='number'
                                step="0.01"
                                className='form-control'
                                value={this.state.price}
                                required
                                onChange={this.onPriceChange}/>
                        </td>
                    </tr>

                    <tr>
                        <td>Category</td>
                        <td>
                            <select
                                onChange={this.onCategoryChange}
                                className='form-control'
                                value={this.state.selectedCategoryId}>
                                <option value="-1">Select category...</option>
                                {categoriesOptions}
                                </select>
                        </td>
                    </tr>

                    <tr>
                        <td></td>
                        <td>
                            <button
                                className='btn btn-primary'
                                onClick={this.onSave}>Save Changes</button>
                        </td>
                    </tr>

                    </tbody>
                </table>
            </form>
        </div>
    );
}

9.6 Output

When you click the “Edit” button, output that you should see is an HTML form with fields: Name, description, price and category drop-down list. These field must be filled out with product data to be edited.

A “Save” button should be seen as well.

Try to edit the form and click the “Save Changes” button. Click the “Read Products” button and see if your record was updated in the list. If it’s there, it means our React app is working.

10.0 How To Delete Data Using React?

10.1 Create “DeleteProductComponent” Class

The “DeleteProductComponent” class will contain the logic and HTML of our app’s “Delete Product” feature.

// component that contains the logic to delete a product
window.DeleteProductComponent = React.createClass({
	// componentDidMount will be here
});

10.2 Change Page Title

When this component was mounted, we’ll just have to change the page title.

Replace “// componentDidMount will be here” of the previous section with the following code.

// on mount, change header text
componentDidMount: function(){
	$('.page-header h1').text('Delete Product');
},

// onDelete will be here

10.3 Handle “Yes” Button

If user clicked the “Yes” button, record will be deleted. It triggers our “onDelete” method below.

Replace “// onDelete will be here” of the previous section with the following code.

// handle single row deletion
onDelete: function(e){

    // product to delete
    var productId = this.props.productId;

    // submit form data to api
    $.ajax({
        url: "http://localhost/api/product/delete.php",
        type : "POST",
        contentType : 'application/json',
        data : JSON.stringify({'id' : productId}),
        success : function(response) {
            this.props.changeAppMode('read');
        }.bind(this),
        error: function(xhr, resp, text){
            // show error in console
            console.log(xhr, resp, text);
        }
    });
},

// render will be here

10.4 Render “Delete Confirmation” Box

Our “render” method contains the message prompt HTML. It asks the user if he’s sure to delete a record.

Replace “// render will be here” of the previous section with the following code.

render: function(){

    return (
        <div className='row'>
            <div className='col-md-3'></div>
            <div className='col-md-6'>
                <div className='panel panel-default'>
                	<div className='panel-body text-align-center'>Are you sure?</div>
                	<div className='panel-footer clearfix'>
                		<div className='text-align-center'>
                            <button onClick={this.onDelete}
                                className='btn btn-danger m-r-1em'>Yes</button>
                            <button onClick={() => this.props.changeAppMode('read')}
                                className='btn btn-primary'>No</button>
                		</div>
                	</div>
                </div>
            </div>
            <div className='col-md-3'></div>
        </div>
    );
}

10.5 Output

When user click the “Delete” button, a message prompt will be shown. It asks the user to confirm the deletion of a record. Specifically, message will say “Are you sure?”.

If user clicked “Yes”, record will be deleted from the database. User will be redirected to the product list. If user clicked “No”, user will be redirected to the product list.

11.0 How To Run The Source Code?

We highly recommend for you to follow and study our well-detailed, step-by-step tutorial above first. Nothing beats experience when it comes to learning.

But we believe you will learn faster if you’ll see the final source code as well. We consider it as your additional guide.

Imagine the value or skill upgrade it can bring you. The additional income you can get from your work, projects or business. The precious time you save. Isn’t that what you want?

By now, you need to download our source codes. To do it, use any download buttons in the next few sections below.

Once you downloaded the source codes, here’s how you can run it.

  1. Extract the files to your server directory.
  2. Set up the “api” by following the README.txt inside the “api” folder.
  3. Open your browser and run index.html
  4. If you can see the list of “product” records, it means your set up is correct.

12.0 Download LEVEL 1 Source Code

FEATURESLEVEL 1
PDO extension usedYES
Bootstrap UI enabledYES
Facebook ReactYES
Create productYES
Read productYES
Update productYES
Delete productYES
Category selection for create and update product.YES
Price display with dollar signYES
SQL file in “dev” folderYES
Download Now

13.0 Download LEVEL 2 Source Code

FEATURESLEVEL 2
All features of LEVEL 1 aboveYES
Search recordsYES
Show records when search box is emptyYES
Routing works for search, page, create, edit and delete pagesYES
Export CSVYES
Multiple deleteYES
PaginationYES
Pagination in searchYES
Go to page numberYES
Limit go to page number based on number of pagesYES
Buttons with glyphiconsYES
Download Now

Do you need more reasons to download it?

MORE REASONS TO DOWNLOAD THE CODEALL
Use new skills for your multiple projectsYES
Save huge amount of time learning React & PHP Rest APIYES
Code examples are direct to the pointYES
Well explained and commented source codeYES
Fast and friendly email supportYES
Free source code updatesYES

14.0 Download ALL LEVELS

This means you will download the LEVEL 1 and LEVEL 2 source codes in separate packages. All check-boxes below must be checked and then your click the “Download Now” button.

Download Now

If you have any more questions, please feel free to contact me now. You can do it by sending a message on our official Facebook page, or via my email mike@codeofaninja.com

Thanks for supporting our website and projects here at codeofaninja.com!

15.0 What’s Next?

Next, we will learn how to create, read, update and delete records with AngularJS, also known as Angular 1.x. Click the following link: AngularJS CRUD Tutorial

16.0 Related Source Codes

Here are the related source codes used in this tutorial.

17.0 Online Resources

Here are useful resources related to React.

18.0 Some Notes

#1 Found An Issue?

If you found a problem with this code, we can solve it faster via Email or FB message, please send me a message via email mike@codeofaninja.com, or via our official Facebook page!

Please be more detailed about your issue. Best if you can provide an error message and your test or page URL. Thanks!

Please feel free to comment if you have any questions, suggestions, found something wrong or want to contribute to this code.

#2 Become a true Ninja!

We constantly add new tutorials and improve our existing tutorials and source codes. Be one of the first to know an update by subscribing to our FREE newsletter. Get a FREE EBOOK as well. CLICK HERE TO SUBSCRIBE FOR FREE!

#3 Thank You!

Thanks for reading our step by step tutorial about React CRUD Tutorial!