The Closest Thing to System Calls
Bob’s fourth in an article series looks at React Native mobile app programming from an embedded systems designer’s perspective. The first part was an introduction to React Native and Flutter. The second part was the React Native eco-system. The third part introduced React Native programming. The fifth part will cover app store releases. The sixth and subsequent will be using Flutter. This month he investigates hooks which are the closest thing to system calls.
Last time we talked about asynchronous programming as one of the two aspects of React Native that gave me trouble. We introduced the concept of the “promise.” Calls to asynchronous functions return a promise. The other problem I had was with hooks – which I will define in a moment. One of the React functions that I imported into my app was the hook: useState. When I first started using it, I missed that it was an asynchronous function. For now, just know that useState is invoked with: a) a state variable (let’s call ours: state); b) a function to set the state variable (let’s call ours: setState); and c) an initial value. I was having (and am still having) fits with useState. I would set state and log its value both before and after I called setState. It never changed. Argh. What was going on?
The problem was I didn’t fully understand hooks. The function which sets the state variable is asynchronous and returns a promise. Thus, the state variable was not set after the call to set it returned. And hooks are what this article is all about. Let’s look at what hooks are and then look at some of the hooks I used most often.
What are Hooks?
Remember that React Native uses the React JavaScript library for some of its functionality. Also, remember that we use React by itself to create web interfaces and React Native with React to create mobile apps. Components are the basic building blocks of React and React Native. An example of a component would be a button. Originally React had class-based components but with version 16.8, they added functional components to allow you to access certain features of React without creating classes. Simplistically, a class component is declared with the Class keyword. And functional components are declared like functions. And when they added functional components, they introduced hooks. Some programmers still feel that class components are better but I won’t get into any “class” warfare at this time. I have done all of my apps using functional components.
React provides to React Native certain hooks that, when imported, allow your program to connect to the internal states and life cycles of functional components (under the hood stuff). A state of your button component could be as simple as: the button is highlighted or not highlighted. When the button changes from one to the other, there is a state change in the component. What are the life cycles of a React Native functional component? When first created, a component is inserted into a virtual DOM? But what is a DOM? The Document Object Model (DOM) is used in web development to define the structure and content of a web page in terms of nodes and objects. React Native uses a virtual DOM to allow commonality of function for JavaScript. Inserting a component into the virtual DOM of a mobile app is when the component will first appear on the screen. It is sometimes called mounting. The second phase of a component’s life cycle is when it is “mounted” and then updated for any reason. And finally, the last stage of a component’s life cycle is when you unmount it or remove it from the screen.
So, hooks help us to access these internals of React Native components like system calls help us access the internals of our RTOS in embedded programming.
HOOK RULES
There are some rules that apply to all hooks:
Hooks don’t work for class components – only functional components.
Hooks are restricted to be initialized at the top level of a functional component. Some aspects can be used at a lower level. Notice that in our useRef Snack (Figure 1 for a screen shot and Figures 2 and 3 for the code) that useState and useRef hooks are called at the top level of the component named App (lines 5-9).
Hooks cannot be called in conditional code, event handlers, loops, after a conditional return statement, or inside exceptions. Thus, you cannot have:
global nonStickyIntervalRef = 0;
if (nonStickyIntervalRef === 0) {
const intervalRef = useRef(0);
} else {
const intervalRef = useRef(1);
}
React hooks must be called in the exact same order for every render.
Thankfully most good editors have plug-ins that catch these while you are writing the code. I used Visual Studio Code.
HOOK DOCUMENTATION
One of my challenges with using hooks in React Native is that virtually all of the documentation for hooks is for React. And thus, all of the examples are for React. Hello Meta! They are not completely comparable! Sorry – every once and a while I need to vent! There are a few sites that have some examples but they are few and far between.
useRef
The easiest hook to understand is useRef. With useRef we can create and update a single changeable variable that exists for the lifetime of the component instance (until it is “unmounted”) that is initialized only once when the component is mounted. After assigning a variable with useRef, we use “variable name”.current to access the value. In a functional component, any regular object that is initialized in the code, is re-initialized every time the component is rendered (when a state change or error condition occurs). If there was a global variable firstTime set to true the first time through the code that indicated that the component was first mounted, you could code something like:
if (firstTime === true) {
var variable = 1;
firstTime = false;
}
Then you wouldn’t need useRef. But useRef prevents us from having this cumbersome firstTime logic.
You can see how useRef works in the useRef/useState Snack [1]. See Figure 1 for a screen shot and Figures 2 and 3 for the code. When you use setInterval (a JavaScript function on line 18 of Figure 2 to run a function at some interval), it returns a reference value to allow you to cancel it at a later time. Think of it like a C file handle. In our example Snack, we have two variables that should be identical (intervalRef and nonStickyIntervalRef). The first uses a useRef variable and the second does not. But since nonStickyIntervalRef is not a useRef variable, it will get initialized to 10 every time the component is updated. You can see on the screen that these two variables which should be identical are not. To preserve the value over time, we initialize it with a useRef hook (intervalRef) and keep the mutable value in the ‘.current’ property.
Lines 5-7 of Figure 2 demonstrate how a useRef variable can be initialized.
useState
This hook is used to allow you to create a state variable for your component. Remember that a component is updated any time the state of the component changes. Thus, changing a state variable will force a re-render.
Look at the useRef/useState Snack code in Figures 2 and 3. Our component (App) has the following states: The initial state when it is “Running” and the two counts are initially at 0 and the Pause/Run button is in the Pause state. Every second, the state changes and both count changes. We have two counters (count and useStateCount) which should be displayed identically. But they don’t! This is because when we increment the useStateCount, the display re-renders before the count is incremented. Thus count is behind useStateCount.
Another thing to keep in mind about useState is that it is asynchronous and returns a promise as a stated at the beginning. The state variable will not be updated until the promise is returned. If need be, you can set a listener to wait for the promise to be updated but that is beyond our scope today.
If you are like me and make lots of programming mistakes while programming, you may sometimes have your app crash because of too many renders. That can happen if you modify a state variable too many times.
Lines 8 and 9 of Figure 2 demonstrate how a useState state variable can be initialized. These provide the variable, the updater function that is called and the initial condition.
useEffect
The definition provided for useEffect in the React documentation is very misleading:
useEffect is a React Hook that lets you synchronize a component with an external system.[2]
Some components need to stay connected to the network, some browser API, or a third-party library, while they are displayed on the page. These systems aren’t controlled by React, so they are called external.
This definition of useEffect, although true, is only part of the story. For example, in the useEffect example Snack[3], we use a useEffect hook to initialize an Interval Timer once when the component is mounted and stop it when the component unmounts. See Figure 4 for a screen shot and Figures 5 and 6 for the code. We have replaced the onceThrough logic from the previous Snack (the useRef / useState app) by using this feature of useEffect. See lines 26-29 of Figure 5. The basic code for a one-time anonymous useEffect function is as follows:
useEffect(() => {
// One time code
return () => {
CLEAN_UP_FUNCTION(); };
}, []);
Another use for useEffect is to call a function when a variable changes. These variables can be specified in a list in the second parameter to the anonymous function between the two brackets: [ ]. See lines 9-24 in Figure 5 in the useEffect Snack
You can use several anonymous useEffect functions in a component as I did in the useEffect Snack. You can see a screen shot in Figure 4 and the code for this Snack in Figures 5 and 6.
useContext
As an embedded developer, you can simplistically think of React Native components as C functions. C functions get parameters passed to them. If the highest level of your function tree creates a variable that is used by the lowest element of the function tree, every function needs to pass that variable down as a parameter to each of the functions in the tree even if it doesn’t use it. With React Native, functional components get their parameters as props. The same thing would apply if you created a deep component tree. If only the lowest component in the tree used a prop from the highest level, every component would have to pass the prop down to it. It gets even more complicated if you use an existing component in the middle of your component tree. You don’t want to change it just to add the prop to get passed down to the lowest level.
Enter useContext[4]. Your top level component can set up some properties, create a context (createContext – see line 4 in Figure 8), add some properties to that context (see line 30 in Figure 9), and subsequently the lower level component (our IndexScreen) can use the various properties set up by the top level component with useContext (see line 36 in Figure 9).
— ADVERTISMENT—
—Advertise Here—
The main use of useContext is to avoid creating global variables and to prevent having to drill props down to lower-level components not unlike you would do in C. See the useContext Snack in Figure 7. In our example we only have two components so it is trivial but believe me it simplifies component design to no end.
useMemo
One would think that this component has something to do with memos or notes of some kind. Instead, it is more like memorize but a little more complicated. The term that is used to describe what useMemo does is memoization. Let’s first describe the problem that useMemo is trying to solve. Imagine that you are designing an EKG on a mobile device. You want to calculate three vital parts of the EKG: a) the P Wave; b) the QRS Complex; and c) the T Wave. These are calculated once per heart beat or about once per second. Let’s call them the vitals. See Figure 10. Each of these requires some resource demanding calculations. The screen graphs the electrical signals in real time requiring the screen to be re-rendered to draw the EKG every 30-50 milliseconds. If your screen component had a component for each of the vitals that performed the calculation, your resource intensive calculations would be updated every 30-50 milliseconds. Using useMemo at the top of the component you could have three useMemo hooks that define the calculation function and what variables you want to use as a dependency for the calculation (in our case something like – heartbeatComplete). Each useMemo returns a value for one of our vitals. Each hook would only run when one of the dependencies get updated. In our case, we only have one dependency for all three hooks. The heartbeatComplete could be that dependency.
useMemo is used mostly for performance. If your calculations are quick, you don’t need useMemo.

If you are designing EKG on a mobile device, it requires the calulcation of P Wave, QRS Complex and T Wave once per heart beat or about once per second. Each of these requires some resource demanding calculations.
useCallback
useCallback is similar in form and function to useMemo except instead of returning a value it returns a function. Again, it is used for performance. In our previous example, instead of three hooks returning three values, we might have one function that calculates our three vitals since they all have the same dependency. Thus, we could use useCallback to only call this function that calculates all three vitals when the startOfHeartbeat variable changes.
To me, these two hooks look like band aids to solve rendering problems in React. And having two almost identical hooks that return either a value or a function seems to miss the Javascript object model. But perhaps there is more to it under the hood that I don’t understand.
Conclusion
These two articles on React Native programming covered the two areas that stymied me in using React Native: asynchronous operations (last time) and hooks (this time). Next time we will wrap up our look at React Native by looking at what it takes to publish your React Native app to the App or Play store – but of course only in thin slices since we will be releasing the app using the expo EAS eco-system to do the heavy lifting.
REFERENCES
[1] https://snack.expo.dev/@rjapenga/useref
[2] https://react.dev/reference/react/useEffect
[3] https://snack.expo.dev/@rjapenga/useeffect
[4] https://snack.expo.dev/@rjapenga/usecontext
RESOURCES
React Native | reactnative.dev
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • OCTOBER 2024 #411 – Get a PDF of the issue
Sponsor this ArticleBob Japenga has been designing embedded systems since 1973. From 1988 - 2020, Bob led a small engineering firm specializing in creating a variety of real-time embedded systems. Bob has been awarded 11 patents in many areas of embedded systems and motion control. Now retired, he enjoys building electronic projects with his grandchildren. You can reach him at
Bob@ListeningToGod.org

![FIGURE 1
A screenshot shows how useRef works in the useRef/useState Snack [1].](https://i0.wp.com/circuitcellar.com/wp-content/uploads/2025/04/411-2024-10-Japenga-Figure_1.jpg?resize=589%2C917&ssl=1)








