Get Started with Modern React: Step by Step
S02・V27: Thinking in React (Part 5)
- We will apply state to our application.
Apply State to our App
Now, we’ve decided that our state should be in FilterableProductTable
.
We’ve determined that the search text the user has entered is state. We will call the state variable filterText
, and give it an initial value of an empty string.
We determined that the value of the checkbox, which when checked only shows products in stock, is the other piece of state of our application. We will call the state variable inStockOnly
, and give it an initial value of false
.
We will need to import useState
from the react
library. We will now inject our filterText
and inStockOnly
state, to both the SearchBar
, and ProductTable
components.
const FilterableProductTable = props => {
const [filterText, setFilterText] = useState(""); const [inStockOnly, setInStockOnly] = useState(false); const { products } = props;
return (
<div>
<SearchBar
filterText={filterText} inStockOnly={inStockOnly} />
<ProductTable
products={products}
filterText={filterText} inStockOnly={inStockOnly} />
</div>
);
};
Now, let’s make use of filterText
and inStockOnly
within our SearchBar
component, via props
. We will make our text input field a controlled component using the filterText
value. And, we will make our checkbox input a controlled component using the inStockOnly
checked value.
const SearchBar = props => {
const { filterText, inStockOnly } = props;
return (
<form>
<input type="text" placeholder="Search..." value={filterText} /> <p>
<input type="checkbox" checked={inStockOnly} /> {" "}
<span style={{ color: "green", fontSize: "smaller" }}>
Only show products in stock
</span>
</p>
</form>
);
};
We can now update the initial values of our state variables in the FilterableProductTable
component to see if we can correctly control the SearchBar
. We will change the initial value of filterText
to be "ball"
, for example. And, we will change the initial value of inStockOnly
to be true
.
const [filterText, setFilterText] = useState("ball");
const [inStockOnly, setInStockOnly] = useState(true);
Save the changes and check if the input fields in the browser reflect these changes. We can now undo these changes.
const [filterText, setFilterText] = useState("");
const [inStockOnly, setInStockOnly] = useState(false);
We will now make use of our state variables in the ProductTable
component, via props
. We can make use of these prop values when pushing ProductCategoryRow
s into the product table.
If the product name
does not include the filterText
the user is searching for, then the product
should not be pushed to the product table. We can implement this by checking the indexOf()
the filterText
in the product name
, and if it is -1
, then return without pushing.
In addition, if the user has chosen only to see products in stock, and the product is not stocked
, then similarly return without pushing.
const ProductTable = props => {
const { filterText, inStockOnly } = props; const { products } = props;
const rows = [];
let lastCategory = null;
products.forEach(product => {
if (product.name.indexOf(filterText) === -1) { return; } if (inStockOnly && !product.stocked) { return; } if (product.category !== lastCategory) {
rows.push(
<ProductCategoryRow
product={product}
key={product.category}
/>
);
}
rows.push(<ProductRow product={product} key={product.name} />);
lastCategory = product.category;
});
return (
<table width="100%">
<thead>
<tr style={{ color: "blue" }}>
<th align="left">Name</th><th align="right">Price</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
);
};
We can now update the initial values of our state variables in the FilterableProductTable
component to see if we can correctly control the ProductTable
.
As we did before, change the initial value of filterText
to be "ball"
. You can see in the browser that the product table only shows products containing the text “ball”. Let’s undo this change.
And again, we will change the initial value of inStockOnly
to be true
. You can see in the browser that the product table only shows products that are in stock. Let’s undo this change.
Our app now looks like this:
import React, { useState } from "react";
import ReactDOM from "react-dom";
const ProductCategoryRow = props => {
const { product } = props;
return (
<tr>
<th colSpan="2">
{product.category}
</th>
</tr>
);
};
const ProductRow = props => {
const { product } = props;
const coloredName = product.stocked ?
product.name :
<span style={{ color: "red" }}>{product.name}</span>;
return (
<tr>
<td>{coloredName}</td><td align="right">{product.price}</td>
</tr>
);
};
const ProductTable = props => {
const { filterText, inStockOnly } = props;
const { products } = props;
const rows = [];
let lastCategory = null;
products.forEach(product => {
if (product.name.indexOf(filterText) === -1) {
return;
}
if (inStockOnly && !product.stocked) {
return;
}
if (product.category !== lastCategory) {
rows.push(
<ProductCategoryRow
product={product}
key={product.category}
/>
);
}
rows.push(<ProductRow product={product} key={product.name} />);
lastCategory = product.category;
});
return (
<table width="100%">
<thead>
<tr style={{ color: "blue" }}>
<th align="left">Name</th><th align="right">Price</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
);
};
const SearchBar = props => {
const { filterText, inStockOnly } = props;
return (
<form>
<input type="text" placeholder="Search..." value={filterText} />
<p>
<input type="checkbox" checked={inStockOnly} />
{" "}
<span style={{ color: "green", fontSize: "smaller" }}>
Only show products in stock
</span>
</p>
</form>
);
};
const FilterableProductTable = props => {
const [filterText, setFilterText] = useState("");
const [inStockOnly, setInStockOnly] = useState(false);
const { products } = props;
return (
<div style={{ fontFamily: "sans-serif" }}>
<SearchBar
filterText={filterText}
inStockOnly={inStockOnly}
/>
<ProductTable
products={products}
filterText={filterText}
inStockOnly={inStockOnly}
/>
</div>
);
};
const PRODUCTS = [
{
category: "Sporting Goods",
price: "$49.99",
stocked: true,
name: "Football"
},
{
category: "Sporting Goods",
price: "$9.99",
stocked: true,
name: "Baseball"
},
{
category: "Sporting Goods",
price: "$29.99",
stocked: false,
name: "Basketball"
},
{
category: "Electronics",
price: "$99.99",
stocked: true,
name: "iPod Touch"
},
{
category: "Electronics",
price: "$399.99",
stocked: false,
name: "iPhone 5"
},
{
category: "Electronics",
price: "$199.99",
stocked: true,
name: "Nexus 7"
}
];
ReactDOM.render(
<FilterableProductTable products={PRODUCTS} />,
document.getElementById("root")
);
Summary
We applied state to our application.
Next Up…
In the next video, we will continue with the sixth, and final, part of, “Thinking in React”.