We want to display the filtered heroes next. The most straightforward way here is to replace state.heroes with the new values. But this is not ideal.
// main.js
// NOT IDEAL. DO NOT USE.
Tiny({
// ...
filterHeroes (event) {
this.setState({ heroes: event.detail.filteredHeroes })
}
// ...
})
Why?
If we replace state.heroes, we won’t be able to pass the full list of heroes down into Filter.js, which creates problems when we filter in the future.
The better way to go about this is to create a new state variable. Let’s call it displayedHeroes. We’ll initialize it to an empty array like state.heroes.
We want to display all heroes when we first obtain data from the Dota API. We can display all heroes by setting both state.displayedHeroes and state.heroes to the same value.
You notice the list of heroes get updated, but the checkbox remains unchecked. Why?
This happens because our naïve implementation of Tiny doesn’t do DOM diffing, so it re-renders the entire DOM. When it re-renders the entire DOM, it doesn’t have any information about the state of each checkbox. (This is why DOM Diffing is important. This is also why Tiny is not ready for production).
But let’s not whine about our naïve implementation, let’s make the checkboxes work for now.
Allowing checkbox state to persist across renders
Before we update the DOM, we need to save the state of each checkbox inside the state object.
The simplest way to do this is create an initial state object that contains all the possible checkbox options. We can create this initial state manually, but what’s the point… right?
We can use JavaScript to get a list of possible values from filters. The shortest way is through reduce.
We can then loop through each value and consolidate the initial state inside a newState object. This lets us update the state once (and hence re-render the component once).
Note: If you’re not comfortable with reduce, you can choose to run 2 forEach loops like what we did inside the template function. Both versions work — neither is better.
We’ll get an initial state like this:
When the user checks a checkbox, we need to update the state. Here, we need to know the checkbox’s id (since the id matches the value we stored in the state object). We also need to know whether the checkbox is checked.
Before we can make this work, we need to abbreviate the value when we store it into the state. (We need this for str, agi, and int)
Saving the checkbox state shouldn’t be in filterHeroes since they’re not the same thing. I propose we call a new function — saveFilterState — when the change event fires.
Even better, we can emit filter-heroes from saveFilterState. This allows filterHeroes to only do one thing — filter heroes. Everything else happens when we save the filtered state.