Pokédex with React
Roid
Posted on August 10, 2020
This is a side project that I've been self studying for the past quarantine days - what day is it exactly? 🤔
There are indefinitely thousands of Pokédex based projects out there no doubt about that, but what I'm trying to convey here is what I've learned so far in React.
Lore
First off, I haven't touched React before and experienced it the first time back in April. It felt weird the first time you play around with it because it wasn't the typical JS,HTML,CSS that many began with and the 'Hello World' you get has already been generated for you through
npx create-react-app hello
With the ongoing quarantine life, it was difficult and I had some breakdowns/meltdowns during those times. Eventually, I had to continue and keep pushing I knew the consequences of not doing anything and continue to procrastinate -felt guilty too you know. So I set the nighttime for coding during the weekdays and chill around with the dudes in Discord on the weekends. It was like that for so long that the quarantine meltdown doesn't bother me anymore. Now that it has come to this, I'd like to show what I've learned in React for the past 5 months time.
Concept
Why did I pick the Pokédex as my first React project? It's simple I like Pokémon, they've provided an open public API which can be pulled from PokéAPI. I've done this before but with vanilla JavaScript,HTML and CSS so it shouldn't be that bad right? Well kind of, I had to study the concepts in React, its components and API hooks that may come useful for the project.
Tools
- React
- react-bootstrap
- axios
- pokeapi
I thought of going react-bootstrap just because I've experienced with bootstrap before and gets the job done. Axios because of its already parsed JSON body.
I'm not going to go through very thoroughly and deep but just explain the procedure and execution on what is going on in the program.
The root/parent of the program (App.js) here uses hooks to be used for Context and a constant for Memo. Context here is, as referred to React Docs, a way of passing down data through the component trees without the need to pass props manually at every level.
App.js
function App(){
const [active, setActive] = useState(true);
const [queryTerm, setQueryTerm] = useState('');
const ProviderVal = useMemo() => ({
active, setActive, queryTerm, setQueryTerm}),
[active, setActive, queryTerm, setQueryTerm]);
return(
<ContextApp.Provider value={ProviderVal}>
...
</ContextApp.Provider>
);
}
There are two Hooks state used and these two should freely be able to pass down the data from child-parent and parent-child through the ContextApp. Every Context object will have a provider to allow any changes that are being made exclusively, this means it will re-render the value (in this case ProvideVal
) whenever the value
prop changes its value basically. Since ProviderVal is a JavaScript function of useMemo()
, useMemo itself is a HOC (Higher Order Component) that return cached values whenever the dependencies inside of the arrays changes.
PokemonCard.js
function PokemonCard({name, url}){
...
useEffect(()=> {
axios.get(url).then((res)=> {
...
}.catch((e)=>{
console.log(e);
})
}, [url]);
return(
...
);
}
export default React.memo(PokemonCard);
The PokemonCard function takes in two props {name, url}
that will re-render whenever it is changed. Changes of {name, url}
takes place in PokemonList.js and Search.js, one is for listing a page filled with pokemons and the other is for searching specific pokemon. Which is why PokemonCard will need to be re-rendered several times through large collections of pokemons and its sprites and other miscellaneous items. The usual axios fetching of the api structure with the [url] as the dependency for changes that will be made in the useEffect()
function. Basically if the url changes, useEffect will need to be run again because it's being included and called by the dependency array.
PokemonList.js
function PokemonList(){
...
useEffect(()=> {
axios.get(currentPage, {cancelToken: new axios.CancelToken((c)=> (cancel=c)), })
.then((res)=> {
...
})
.catch(){
})
return ()=> {cancel()};
}, [currentPage, pageNum]);
...
export default React.memo(PokemonList);
}
I found this article about Axios Cancel method here. It's really well done!
The axios fetch here is almost the same but with the [currentPage, pageNum] as the dependency array. The very last bit for exporting the function is being wrapped around the React.memo()
higher order function.
ContextApp.js
import {createContext} from 'react';
export const ContextApp = createContext(null);
Creates a context object and initialized.
Search.js
function Search(){
const {queryTerm} = useContext(ContextApp);
const name = queryTerm.toLowerCase();
const url = `https://pokeapi.co/api/v2/pokemon/${name}`;
return <PokemonCard name={name} url={url} />;
}
Here's a snippet of the Search function which has the useContext()
function that refers to the {queryTerm} variable. It returns the PokemonCard component that has custome {name} and {url} from the {queryTerm}.
Closing
I guess I'm liking it? I'm not sure but I will continue with this project because there's still potential in using this API for more React APIs and concepts that I might've not known about. You can contribute to this project by creating PRs or Issues.
Posted on August 10, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
February 25, 2022