Weekly web-dev learning #2

This week I am writing about my love of arrow functions and the differences between class-based components and Hooks when it comes to Redux.

Photo by Ferenc Almasi on Unsplash

Hi again, I’m glad to write a second edition of the weekly web-dev learning series. It’s an important achievement to make it part of a routine. Now the challenge is to make it for the third time and so on!

This week I studied two different projects from two different instructors. The first is a streaming application from Stephen Grider’s course, and the other is an event attendance application by Neil Cummings’ course. The streaming application lets the user create stream IDs and make live streams from there using OBS. The data is stored in a JSON file of a dummy API server. The event attendance application lets the user create events and attend one of those. The event’s city and venue are selected precisely from Google Maps API and then the coordinates are shown as a pin on the map in the event details page. The data is stored on a Firebase Firestore database.

Both projects are based on React and Redux, but the first one is written in class-based components and the second one uses React Hooks syntax, which is actually my favourite over the other.

Yeah, I love Hooks over class-based components and that will be my preference if I can start my own project without any guidance from a course, but I am aware of the fact that class-based components are not going to be deprecated in the near-future and they can be found in the applications of many established companies. For example, it is highly likely to come across class-based components if I start working for one of those very international, big companies based in Amsterdam, assuming they are not brand new. Smaller ones, for example in Utrecht, might be assigned with a new project so that the team is more likely to use Hooks. I dream myself in Utrecht, so I am more hopeful of working with Hooks. Besides React, I must admit that the idea of working at an international company in Amsterdam is also highly exciting. Anyways, let’s return to the technical topics.

In love with arrow functions

I also discovered that I wholeheartedly prefer arrow functions over the classical syntax. I saw a slight advantage of arrow functions in Stephen Grider’s course which is about the need for binding the function. When you write a function in classical syntax like this:

function handleSomething() {
     this.setState({ someState: someValue })
}

…then you need to bind this function in the constructor of that class like this:

constructor(props) {
    super(props)
    // some other code

    this.handleSomething = this.handleSomething.bind(this)
}

That row with bind function is necessary to use this in the function, but I never appreciated the meaning of doing such statement. So, learning that arrow function automatically binds the function from Stephen Grider’s course was a revelation. From that on, I now am a fanatic of arrow function everywhere, despite the fact that it takes more time to write one, especially exporting default. If I’m wrong please correct me but Neil Cummings was writing a function like this:

export default function SomeComponent() {
    return <div>Hello</div>
}

Then as an arrow function fanatic, I needed to write:

const SomeComponent = () => {
    return <div>Hello</div>
}

export default SomeComponent

It definitely takes more time to write because of the = () => part even if we weren’t exporting the function. But hey, I have the rafce snippet that writes the arrow function React component for me! See the VS Code extension number 3 in my recent blog post.

As a result, I always write arrow functions even though Neil Cummings write functions in classical way in the course I follow. I actually got the habit from his other course in TypeScript, then as I mentioned, fell in love with arrow functions after the revelation in Stephen Grider’s course.

Redux in class-based components, Redux in Hooks

I was normally going to start that “other” course this week as it is re-recorded, but it uses MobX instead of Redux. I wanted to practice more Redux after the streams app. Well, I still haven’t clarified Redux myself yet but the events app after the streams app provided me a list of differences for the usage of Redux in class-based components compared to the Hooks.

First of all, the Redux part was the same along the two projects. Major difference between Stephen Grider and Neil Cummings was that Grider separates the action creators from reducers and the types from actions. Everything’s separated. Cummings writes everything in a reducer. So it has been a bit more confusing while coding along. But revisiting the code from Github solved some problems about this.

What I noticed between these two projects the most is how we include the states and actions in the components. In the class-based components, I need to use connect()() function, which really has two spaces for parameters, directly after export default. The second space takes the component name, and the first one has two arguments: mapStateToProps function and an object of actions that you want to import. Like this:

export default connect(mapStateToProps, { anAction, anotherAction })(SomeComponent)

And the mapStateToProps looks like this:

const mapStateToProps = (state) => {
    return { stateName: state.reducerName.someKey }
}

Please note that we are assigning a value here to stateName the value of someKey. In the streams app, the key of any stream was its id, and the value was the actual stream object. Therefore, there was a second argument next to state, as ownProps. And it was used as state.reducerName[ownProps.match.params.id]. To be more clear, see the code I am trying to explain. Here the reducerName is the name of the key you declare in combineReducers function:

export default combineReducers({
    reducerName: someReducer,
    auth: authReducer,
    anything: anotherReducer
})

Best practice here is the auth one, but you can name things as you want. Oh, by the way, you need to import connect and combineReducers whenever you will use them.

Now, when you use Redux states and actions as props in React Hooks, you don’t use connect with mapStateToProps. Instead, you import actions directly and assign or destructure the desired states from useSelector(). For example:

import { useSelector } from 'react-redux'
import { actionOne, actionTwo } from './actions'

const SomeComponent = () => {
    const data = useSelector(state => state.reducerName.data)
    const { someStateKey } = useSelector(state => state.anotherReducer)

    return (...)
}

export default SomeComponent

One thing I notice but am not sure is that the streams app uses actions directly as props within the component. But the events app dispatches those actions within the component. At first, I thought that it is the difference between class-based components and React Hooks, but then found out that Stephen Grider already dispatched the action within the action creator:

export const fetchStream = id => async dispatch => {
    const response = await streams.get(`/streams/${id}`)

    dispatch({ type: FETCH_STREAM, payload: response.data })
}

…whereas Neil Cummings keeps the action creator simple:

export const listenToEvents = events => {
    return {
        type: FETCH_EVENTS,
        payload: events
    }
}

…and then he dispatches the action right in the component, first calling the useDispatch hook.

const dispatch = useDispatch()
...
dispatch(listenToEvents(events))

Whenever an action is used in the events app, the action creator function is wrapped as an argument to dispatch() function. I think it takes a few more example projects to learn the convention.

Other things

I used Google Authentication API to utilise a login system for the streams app. And then Google Maps API and Firestore for the events app. All of these I consider as guided experiences and are subject to change. Especially Google Developer Console has changed drastically so that I found the pages in the videos based on my instincts rather than following the video. Therefore, I don’t want to write them in this blog post. It is already guided in the documentation of these services and they change so quick. I will refer to these documentation and maybe my Github repositories for revisiting examples when I need them in future projects.

I also used Formik for the first time and I feel that it will be the go-to forms solution rather than Redux Form or React Final Form. But I prefer mastering at Formik in the next “other” course of Neil Cummings. Right now I am aiming to understand Redux better.

Currently I still continue the events app from Neil Cummings’ course, and it will probably finalise next week. I sometimes feel like I am coding along not understanding what’s going on. Stephen Grider was better at explaining things, but his examples were too simple. The difficulty is a better match for me in the events app, but Neil Cummings does not explain what’s going on as good as Grider. So who knows what I will learn next week?

Well, see you then in the third edition of this blog series!

Leave a Reply