Home

I Like To Build Things That Way

06 December 2019

I had a bad experience with Redux back in 2016 while building a large and complex webapp with several other front-end developers. The API of Redux was just too verbose. Integrating it into React was not straightforward too.

The name reducer was one of the many concepts it brought to me but always confused me as a non-native English speaker. In the end, I had to write a lot of code across many files in order to complete even one simple AJAX request and did data update/sync with Immutable.js.

It was painful.

The idea of Redux and immutable data sounds very right at first, which probably will improve the code quality and maintenance. However, in a way by sacrificing too much energy of developers like me. It's a mistake to choose something only by the popularity.

Then I switched to use MobX and never came back.

I learned that a good API is designed to help people doing their job and saving their time. No matter how right the concepts may sound like and whether it be pure or in-pure, mutable or immutable, they'd be better hidden inside.

Anyway, I love React itself as a view library.

React Hooks

React hooks have been introduced to React for quite a while now. I've been learning how to use them since the beginning. They surely have some advantages over the class component. However, I still haven't picked them for new projects in the company mainly because of its API.

In the official documentation page the code looks clean. Well, that's right.

function Example() {
  const [count, setCount] = useState(0)

  /* .. */
}

But the situations are always more complex in real-world projects.

Suppose you're building a big form page with lots of input fields. How would you write it with React hooks? Maybe like so:

function Form() {
  const [count, setCount] = useState(0)
  const [name, setName] = useState('')
  const [school, setSchool] = useState('')
  const [weight, setWeight] = useState(0)
  const [height, setHeight] = useState(0)
  const [education, setEducation] = useState('')
  const [age, setAge] = useState(0)
  const [major, setMajor] = useState('')
  /* many many more */

  /* .. */
}

As you can see it becomes not that clean. One quick alternative way is to wrap all the states into a separate hook.

function useFormState(initial) {
  const [fields, setFields] = useState(initial)
  const _setFields = (name, value) => {
    if (name in fields) {
      setFields({ ...fields, [name]: value })
    }
  }
  return [ fields, _setFields ]
}

function Form() {
  const [fields, setFields] = useFormState({
    count: 0,
    name: '',
    ...
  })

  /* .. */
}

Things are getting complicated if one of the fields including a deep structure like an array (for multiple options etc.), then I have to handle that properly in the _setFields function. It's much like the old setState in an implict way.

Another solution is to use the builtin useReducer.

It's a strong warning sign to me as the name reducer recalls some bad memory. Also it makes me wonder if there are too many concepts in React hooks like Redux did.

Why not more explicit

There must be something wrong if developers need to write much code for compromising the API, and not the other way around. At least the API can be improved.

Fortunately, Svelte has proved that things can be done naturally and elegantly.

let count = 0;
let name = '';
let options = [];
  ...

No more extraneous code. It seems Svelte was designed from a developer's perspective, rather than in the pursuit of pure functional programming.

I like to build things that way.

There's an inspiring quote about math but sometimes I hope it's same to programming.

Beauty is the first test: there is no permanent place in the world for ugly mathematics... It may be very hard to define mathematical beauty, but that is just as true of beauty of any kind — we may not know quite what we mean by a beautiful poem, but that does not prevent us from recognizing one when we read it.