React - Passing data between components… with Pokemon as an example!
Passing data between react components can be simple, but in some occasions, it can be very tricky. While from parent to child, and vice-versa, can be a straightforward process, you’ll need to use the tools that react and javascript give you, in order to pass data to-and-from siblings (that is why Redux was invented).
Let us focus first on the most simple ways of passing data from one component to another. And, to make it more fun, we’ll use Pokemon!
How? To explain this concept, we are going to create/simulate a Pokemon battle, just like the good old first generation games for the GameBoy!
Note: you can find the source code inside this repository, with instructions on how to run and install the app, if you missed something or got stuck.
Setup
First, let us create a new react application. Click here and it will send you to the create-react-app repository, a tool that let you create a new react application in no time. All the instructions can be found there. Then, create a react application (you can call it pokemon-battle). After that, inside the src folder, create a components folder and inside of it, a Pokemon and a GameManager folder. Each one must have an index.jsx file, where our components will be written.
Start your app, open your browser and go to localhost:3000 to see your app running! (port 3000 is the default one, but it can be different in your case)
After checking if everything is running, replace your App.js file with this one:
Your application will break because you don’t have the GameManager component. But if you put the next code samples inside each corresponding index.jsx , the application will start running again.
Parent-to-Child
A Pokemon battle consists of a fight between two Pokemon, selected by each trainer. The first Pokemon to attack is the one with normal status and with the higher speed (there are other variables to take into account, but let’s keep it simple). If the HP of a Pokemon reaches 0 (zero), the Pokemon faints, and the one that is left standing wins the battle. For a Pokemon to attack, the trainer must choose one of the attacks/moves from the list of moves learned by the Pokemon.
Passing values from a parent component to a child component is easy. You just need to pass the values as props of the child element. To demonstrate that, the code below represents the part where the trainers choose the Pokemon they are going to send to battle. In this case, a Squirtle and a Charmander.
When we get to the render function of the GameManager component, you can see that the information about Charmander is passed on to the first instance of the Pokemon component. Each prop is set one-by-one.
On the other hand, the information about Squirtle is passed through a javascript object (the constant at the start of the code), using the spread operator (ES6). Each key-value of the object will be treated as a prop of the child component.
Now that we have passed the information about our two Pokemon, let’s extract that information inside the Pokemon component. We do this by accessing the props attribute of the component. You can see that in the code below.
As you can see, by accessing the props attribute of the component, we are able to render each Pokemon information inside the render method. Note that the props of a component are not limited to the render method, they can be accessed within any other method that you create!
Child-to-Parent
Remember, for a Pokemon to attack, its trainer must choose a move from the ones that it has learned. When the trainer decides which moves the Pokemon should use, that information must be passed to the GameManager component. But how can the Pokemon component pass the data about the move to the parent component?
A direct-ish way of doing this (and the most common), is to pass a function that will work as a callback. This method must receive the child data that needs to pass to the parent as arguments. Take a look at the getAttack method. The method signature tells us that it has 2 parameters. We then pass that same method as a prop of the child component, with no arguments.
Seems weird, right? Let’s look at the new Pokemon component.
A wild attack method appeared! If you notice, this method, when executed, calls the same method we have passed as a prop of the Pokemon component. And this time, it takes 2 arguments. In this case, Pokemon name (which is a prop of the component) and the selected attack/move object.
To make this more interactive, the attack method is used as the callback method of the onClick event, used in the buttons below. When we click on the button to choose a move, it calls the attached method, in this case, attack.
What attack really does is simply calling the getAttack of the GameManager component. This way, the Pokemon name and the move selected, are passed to the parent through that function!
We then store that information in the GameManager state. By changing the state, the render method will be triggered again, thus showing the message created by the showMessage method. Because we stored the passed data into the state, all methods that use it can have access to the Pokemon name and the attack/move selected.
For simplicity, the showMessage only shows a message with the name of the Pokemon that performed the attack and that same attack name. By passing other methods to the child component and store to the parent's state the data passed from the child, we can make more complex operations. An example was passing the information about the attack to Pokemon that will receive it and determine the hit points it would lose. Or determine if the receiver would evade the attack.
And that’s it! The Pokemon component (child) passed data to the GameManager (parent).
Conclusion
These are just two quick examples to show you how components pass information between each other. There are other ways to do this, and other situations for each case to be used, but this is the basic logic for when it comes to passing data.
You can make a mix of these two ways for siblings to communicate or if they don’t have any relation between them (a parent component), you can create a solution using Redux.
Well, that’s all for now! Now go catch’em all!
If you want to know more about React, look at the library docs (they are very good), or read some of my colleague’s posts below:
- Introduction to React — where to start?
- Implementing Conway’s Game of Life With React — Part 1
- Implementing Conway’s Game of Life With React — Part 2
- Everything Redux — Part 1
Pokémon © 2002–2018 Pokémon. © 1995–2018 Nintendo/Creatures Inc./GAME FREAK inc. TM, ® and Pokémon character names are trademarks of Nintendo.
No copyright or trademark infringement is intended in using Pokémon content on this post.
I’m currently a Ruby-on-Rails developer at Runtime Revolution that still likes to play the good old Pokemon games for the GameBoy. Go check our website to know us more. Oh and we’re hiring!
Top comments (0)