React/Redux - How to handle/organize events

I’m currently working on that drum-machine quest and I’m wondering which is the best way to handle/organize events (but the question is not specially for that quest):

Solution A = 1 handler-function:
In my parent component there is one handler+if/else:

handleEvent(e) {
 if(e.target.id=="selectbox1") ...select1-stuff...
 else if(e.target.id=="selectbox2") ...select2-stuff...
 else if(e.target.id=="button") ...button-stuff...
}

Solution B: several handler-functions

handleSelect1Event(e) ...select1-stuff...
handleSelect2Event(e) ...select2-stuff...
handleButtonEvent(e) ...button-stuff...

Both solutions will work but is there any reason that A or B may be better?
In A all the logic is centralized. But B seems to have a simpler code-structure (no if/else)
Maybe it’s not important at all.
Thanks

Solution B is imho better that you can move your handlers around (e.g. to a different component). Also what if you decide to change id’s or get rid of them altogether? To B functions you can pass anything you want as an argument (event, string, nothing).

1 Like

I’ve been thinking about your answer and you are obviously right! I don’t understand that I didn’t come to the answer myself. Seems I’ve built too much ugly js-code in the last years so I got used to some bad manners. Time to refactor.
Thanks.

If we talk about these topics, we should always ask questions.
What do we want to do with our code and why we do it that way.
That’s why I always ask myself, what are the most annoying things in my daily professional dev life.
Most of the time it’s code, that is hard to read, hard to understand and hard to change.

I build my stuff with TDD in the smallest possible way and refactor later.
I try to be very explicit.
I try to use conditionals very rarely, because more logic means more complexity.

Personally, I prefer what happens + who is the actor in React, e.g.
handleChangeEmailInput()
handleChangePasswordInput()
handleClickLoginButton()

This is very explicit and expressive.

Some people argue with DRY, but I think DRY is too machine-focused and not user/dev-focused.
If it’s really repetetive, like a simple onChangeHandler for a form,
I go with the more generic:

handleChangeFormInputs = (event) => {
  this.setState({
    [event.target.name]: event.target.value
   });
};

In the end, my simple benchmark question is:
If I would see this code for the first time side-by-side, which one would be easier to understand?

1 Like

Thank you for your answer which goes more for Solution B and beyond.

For me the “most annoying thing” is: if I’m afraid to change some part of a code because I don’t know what will happen somewhere else (probably some days later…) in a different area of that big code monster. That is usually related to long, complicated, uncommented and overloaded functions.

I never tried TDD (test first, I believe) but maybe that will help. If all functions are tested and all tests are still passing after your changes the risk of making a mistake is much lower.

And yes: handleChangeEmailInput() is clearer than: handleEvent() which could be anything.

This is where Testing kicks in.
If you are afraid to change code and to take responsibility for the changes (perfectly understandable!),
then it’s time for better Testing.
Being afraid is one of the most annoying things.

It’s quite the opposite. Other than taking a few extra bytes, the machine doesn’t care if the implementation is copy-pasted all over the place or not. DRY (Don’t Repeat Yourself, for the benefit of readers) is about maintainability, where if you need to make changes, you only need to change things in one place rather than everywhere it’s been pasted. It’s literally the “factoring” part of refactoring.

However, I don’t see any kind of DRY violations in writing handlers like you mentioned. Repeats in names are just naming conventions, and what with editors having autocomplete it’s not even such a chore to have verbose names. I rather like the handler naming convention you have, actually.

I’m thinking of something like two handlers for two input fields,
that currently do the same, like setting a state, e.g.

const handleChangeEmailInput = (event) => {
  this.setState({
    email: event.target.value
  });
};

const handleChangePasswordInput = (event) => {
  this.setState({
    password: event.target.value
  });
};

So we refactor it into:

const handleChangeFormInputs = (event) => {
  this.setState({
    [event.target.name]: event.target.value
  });
};

Now it would be easier to maintain it, e.g. if we want to change the structure of our state.
On the other side, if we want to change the behaviour of only the EmailInput,
we would have to move it to the pre-refactor form or add some conditionals,
what would increase the complexity.

One thing you could do is still keep separate method names, but make them delegate to the generic method To wit:

const handleChangeEmailInput = handleChangeFormInputs
const handleChangePasswordnput = handleChangeFormInputs

That lets you keep the naming convention in your props and allow it to change independently if you need it to.

2 Likes

I found that introductionary article:

And checked out (a little bit) that jasmine-api that can be used within codepen:
https://jasmine.github.io/

So I will give it a try on my next fcc-project

If you want to learn it with React,
I recommend this one: https://learntdd.in/react/

1 Like