The official ReactJS docs include a chapter called Thinking in React: https://reactjs.org/docs/getting-started.html#thinking-in-react.
Important note
Many React users credit reading Thinking in React (https://reactjs.org/docs/thinking-in-react.html) as the moment React finally clicked for them. It’s probably the oldest React walk-through but it’s still just as relevant.
Let’s try and capture the most important, and still relevant, parts of that article.
First of all, when we create a website with ReactJS, we need to think about how we will construct our components. Not HTML blocks, not DOM elements, but components. Ideally, each component will be a separate entity, which either creates a state or consumes props, or sometimes both. The component is the smallest part of our app, just like atoms are the smallest parts of our world.
Okay, I realize atoms can be further divided into neutrons, protons, and electrons. And ReactJS components can be divided into parts that handle the logic and the actual rendering. However, both atoms and ReactJS components are the basic building blocks in their respective realms.
Now that we have our components imagined, we need to know how they should interact with each other. Let’s go back to the ReactJS docs, where we will find a great chapter, Composition vs. Inheritance: https://reactjs.org/docs/composition-vs-inheritance.html.
This article is very clear in stating that ReactJS components should be composed, and not stacked in a strict hierarchy. This basically means that any child component should be created in a way that it could be reused by other parent components throughout the app. This promotes the high reusability of atomic components, and at the same time, reduces the amount of code needed to create an application.
Now that we have the theory down, let’s move on to specifics. How do we compose ReactJS components in practice? By using state and props. What are those, you may ask? Well, I’ll be glad to explain!
Both state and props (short for properties) are plain JavaScript objects. The big difference between them is that props are read-only, while state can be changed within the component that manages it. State is the source of truth, while props are the representations of the current state of the application. Let’s take a look at a minimal code example:
import React, { useState } from "react";
const PrettyButton = ({ updateCount, count }) => {
return (
<button onClick={updateCount}>This was clicked {count} of times</button>
);
};
export default function App() {
const [counter, updateCount] = useState(0);
const handleClick = () => {
updateCount(counter + 1);
};
return (
<div>
<h1>Hello There!</h1>
<PrettyButton count={counter} updateCount={handleClick} />
</div>
);
}
You can play with this sample code online thanks to this CodeSandbox: https://codesandbox.io/s/admiring-fire-68k94x?file=/src/App.js.
From the preceding code example, you can see that the App
component creates the counter state, and the function responsible for updating it. PrettyButton
consumes this state in the form of props. PrettyButton
cannot change the value of counter
or updateCounter
directly.
If we were to write another parent component that needed to use PrettyButton
, it would need to create its own counter
and updateCounter
states. And thanks to that, every instance of PrettyButton
we may want to use in our web app will be independent of the others.
We may also find ourselves importing multiple child components in the main App
component. This is totally natural. We may have an app with a button, a text, and a modal, all of which need to display the number of times the button was clicked. All we need to do is add the necessary components to the parent and pass the counter
prop. The state is mutated only in the parent and then fed to the children.
Now we arrive at the moment where we need to decide which component should handle the state change. In our simple code example, the answer is obvious: we have only one parent. In the real world, this question may be much more difficult to answer. Luckily for us, we will look at state management strategies throughout this entire book. I hope, after reading this book, that you will be well equipped to choose the best place to store and manage your application state in your React Native app.
In the previous section, we went over high-level aspects of writing code in ReactJS. It’s good to keep in mind the patterns we looked at, as they are just as useful in React Native development. And since we’re familiar with ReactJS, we are ready to dive into the world of native apps written in JavaScript.