The philosophy of React: Declarative rendering
A core concept behind React is the idea of declarative rendering vs. imperative rendering.
Vanilla JS and libraries like jQuery are imperative. For example, when you want to change the class attribute of a DOM element, you directly command the element to change its class by calling a function like
.addClass(). (Trivia: impero means “to command” in Latin)
function A function B function C | | | |__________. | .___________| | | | v v v DOM element
React is declarative. When you want to change the class attribute of a DOM element, you do not directly send a command to the element. Instead, you first declare how you want the class of the element to be derived from the state and props of the element’s component. Then, you command the state of that component (or the state of its parent) to change, using
setState(). Then, when
render() runs, your targeted element will automatically update its class attribute according to the declarations you made, without any direct commands from you. The element will react to its component’s new state and props. (Trivia: declaro means… “to declare” in Latin)
function A function B function C | | | |__________. | .___________| | | | v v v state + props | | v DOM element
The advantage of declarative rendering over imperative rendering becomes clear when you have many different elements whose attributes depend on several different pieces of data (the header of a webapp is a common place to find elements like this).
With imperative DOM manipulation, you would have to send a command to every element whenever any one of those pieces of data changes. The functions that send those commands could be spread out throughout your code. Those functions must also take into account the other functions that also affect it. The logic controlling a particular element’s attributes is fragmented and distributed, making it very difficult to track down bugs.
With declarative DOM manipulation, a single element would have all its attributes defined in a single spot within your
render() function. The functions that affect the state and props that those attributes are derived from would still be spread throughout your code; however, those functions no longer need to take into account the other functions that also affect those state and props. All of the logic controlling a particular element’s attributes is concentrated in the single spot in
render() where you derive those attributes from state and props, making it very simple to track down bugs.
In imperative rendering, many different functions push information down to an element. In declarative rendering, an element pulls information down from only state and props.
The concept of declarative rendering has a counterpart in the world of writing and sentence composition. In many style guides, it’s a common instruction to keep related words together; adjectives that modify a noun should be in proximity to that noun. React and its policy of deriving element attributes from state and props offers us a simple way to follow this rule in front-end development.