Programming user interfaces in a maintainable and scalable way lets programmers think about one single visual component at a time.
Describe the interface as components that render state
Each component of the interface is a function that gets state and returns how to draw this state on the screen. These components can be composed to form bigger parts of the user interface. Given a certain state this composition should always produce the same visual output to make your software predictable.
Let interactions only change state
User interactions should only change the application state. Passing the new state to the top level component results in a new visual output. This makes adding new features and testing easier, because each interaction is a function that gets state and returns a new one.
Reduce runtime errors with static type checking
In a statically typed language the compiler is able to check if the state passed to each component passes its required input types. This catches errors early before runtime and deploying to production.
Provide isolation with immutable data structures
Defining the state as an immutable data structure guarantees that each component is isolated and cannot influence the state of other components. This is because changing an immutable data structure returns a new one instead of updating its value in place.
Simplify debugging with one single state
Using one single persistent immutable data structure as your state makes very helpful debugging techniques like “time traveling” possible. Time traveling is the possibility to record user interactions and playing them back later to reproduce bugs. Updating a persistent immutable data structure returns a new one that shares most of its structure with the old one. This prevents big memory consumption for big amounts of updates.