This code listing steps through the process of making a moderately complex web user interface that reacts to user actions. It presents a list of spells and allows the user to filter the list by checking/unchecking a series of checkbox form elements. The code must keep track of which boxes are checked in the React Object state. The list of spells must update dynamically when changes are detected. This is what we mean by a reactive interface.
We see a new import
here from the lodash
library. lodash
has many useful functions for working with arrays, maps, collections,
objects, and functions. In this code, we are going to use it primarily
for sorting our data more easily.
An objects constructor is called once, when the object is first created
or instantiated. For React Component
objects, we call super()
to
trigger the generic Component
constructor, then initialize our default
values for the state.
filters
will let us know which spells to display, based on the character
classes that are active (e.g. show only spells that clerics and druids can use).
All of the items are true
to start so that all spells are shown.
Our objects methods (aka member functions) share data and communicate with each other
through the special this
object. this
refers to this instance of SpellTable
.
If we don't bind()
this to each of our functions, those functions can't
access object data such as state
, props
, or other methods.
The componentWillMount()
method is inherited from React Component
. It is called before the component is displayed. It's the
best place to load the data that our component will need. Here we take the
spell objects that we imported from "./data/spells.json"
and we sort
them by level. We call the setState()
function that is part of React Component
in order to update the state and trigger our render()
function if needed.
toggleFilter()
gets called when one of our filter checkboxes is
checked or unchecked. It changes the state
of the entry in the filters
map
to true
or false
(the logical opposite of whatever it currently is).
clearFilters()
sets all of the filters to false
. No spells will be shown,
but it makes it easier for the user to select just one character class.
allCharClasses()
sets all of the filters to true
so that all spells are shown.
All React Components must define a render()
method. This returns the JSX/string
component that is rendered to the screen (or null
if nothing is to be displayed.)
Our render method is building an HTML table (with Bootstrap css classes) that
shows all of the spells that are active. It defines th()
as an internal
function to map html th
elements to an array of strings. This creates the
table header.
We look up the list of active filters from the state
and then call
filterSpellsByCharClass()
(see below) to find the spells
which should be active.
We map those spells to SpellRow
components calling spells.map()
We have two buttons that make it easier to clear or check all of the
filters. They call this.clearFilters()
and this.allCharClasses()
(see above).
We call the IconCheckBox
Component function (below) to create a checkbox for each D&D
character class. When any of these boxes are changed (checked or unchecked),
passing toggleFilter()
, the active status, and the character class as properties.
The inner check()
function returns the ClassIcon
for a character class, or null
if this spell isn't available to the class.