React Weather App [Episode 2] : Sorry, did I forget to explain hooks?
Let's build a functional component with hooks! :)
Hey there!
So in episode 1 - which was the last post, but also the first - we learned how we can use an API to retrieve some data for our app, and also how we can create a Redux Store to make this data available to the entire app.
We also discussed the use of two hooks that come with Redux:
useDispatch, which will allow us to update the state.
useSelector, which will allow us to subscribe to the store, and be able to use its state to make component "React" to changes in the data.
Lets create some functional components
I actually wanted to jump right into the specifics of the components I designed for the app, but I felt like I might have been a bit harsh starting with Redux and dropping hooks names like a crazy person. So today I'll try to shed some light on the concepts of functional components and hooks, as we'll extensively use those for the app.
Why "functional" component? Well, when I first started reading React, I quickly realized there had been a shift in the way React components were written, following the release of a new feature called hooks.
According to the react documentation, "Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class."
Hooks made functional component sexy again by bringing state management into them and to be honest, that is pretty much everything I know about it.
A functional component is a function, which return JSX content to be rendered.This is a basic functional component structure:
const SimpleComponent = (props) => {
/*Do stuff in javascript here*/
return (
{/*some JSX content*/}
)
}
export default SimpleComponent
Now, to use this component in any other component, we just need to import it and initialize it like this:
import SimpleComponent from './SimpleComponent';
/*then in component*/
<SimpleComponent parameter={"1234"} otherParameter = {"5678"}/>
You can see that this component has a props parameter, which is an object and contains the properties we passed to the component when it was initialized. Inside the component we can use props.parameter and props.otherParameter.
const SimpleComponent = (props) => {
const bothParameters = props.parameter+" "+props.otherParameter;
return (
<div>{bothParameters}</div>
)
}
export default SimpleComponent
This will return a div containing the value "1234 5678"
So inside a functional component, we can do some pre-processing of the data we wish to display and might have gotten through props. Then, we return some JSX content we build using this data.
But we need this component to be able to update automatically whenever certain data changes happen, and this is where we use hooks!
For example, let's say our simple component is a button, and that when we click on this button, the component color switches to red or blue.
To do that, we must add a useState Hook to our component, so we import useState and then declare a hook.
import { useState } from "react"
/*Then in component*/
const [buttonColor, setButtonColor] = useState("blue");
What we did here is create a state for our component, we have a hook named buttonColor, which is initialized with a string value here, "blue". Now, the component will "watch" the state and whenever it is redefined, the component will render with updated state values.
We also have a setter function which we can use to redefine the value of this hook. Using this setter, we define a function which will switch the butttonColor value from blue to red, like this:
const changeButtonColor = () => {
if (buttonColor == "blue") {
setButtonColor("red")
} else {
setButtonColor("blue")
}
}
In the "return" section, we create a button and we use the hook to define its color:
return (
<div style = {{"background-color":buttonColor}} onClick = { () => {
changeButtonColor();
}}>Click me I'm a button!
</div>
)
Now, you can see that this button has an onClick event defined, which is a call to changeButtonColor() function. And now our button will be rendering each time we click on it and update its background color.
Congratulations, you've used your first hook :)
import { useState } from "react"
const SimpleComponent = () => {
const [buttonColor, setButtonColor] = useState("blue");
const changeButtonColor = () => {
if (buttonColor == "blue") {
setButtonColor("red")
} else {
setButtonColor("blue")
}
}
return (
<div style = {{"background-color":buttonColor}} onClick = { () => {
changeButtonColor();
}}>Click me I'm a button!
</div>
)
}
export default SimpleComponent
Now, to illustrate things, I'll upgrade the component a little. What we will do is turn some of the constants into parameters, and use the props values. In this new version, we'll be able to pass the colors as parameters, to the component:
import { useState } from "react"
const SimpleComponent = (props) => {
const [buttonColor, setButtonColor] = useState(props.firstColor);
const changeButtonColor = () => {
if (buttonColor == props.firstColor) {
setButtonColor(props.secondColor)
} else {
setButtonColor(props.firstColor)
}
}
return (
<div style = {{"background-color":buttonColor}} onClick = { () => {
changeButtonColor();
}}>Click me I'm a button!
</div>
)
}
export default SimpleComponent
We just have to initialize the component like this:
<SimpleComponent firstColor = "yellow" secondColor = "green"/>
And there you go, a customizable color switching button.
We used useState here, which creates a local state for the component and is a good start to grasp the concept of hooks, but for our project, as you may remember, we'll mostly rely on useSelector to define our hooks, because we use data from the Redux Store. The hook declaration syntax is a bit different, and instead of a setter, we have useDispatch to update the store.
Next Episode, now that we know then concept of hooks and functional components, we'll create the first components for the App: a search field and a current weather "card" presenting whatever data has been retrieved from the search.
Hope you enjoyed this.