Understanding the Drawbacks of React Hooks: A Critical Look
Written on
Chapter 1: Unpacking React Hooks
Since the introduction of Hooks in React version 16.8, they have swiftly gained traction within the React community. They address the issues related to Mixins and work seamlessly with Function Components and the Fiber architecture. However, it's essential to recognize that no tool is without its flaws. Even if you appreciate a technology, understanding its shortcomings is vital for effective utilization. While numerous articles laud React Hooks, this piece aims to explore their less elegant aspects.
Section 1.1: The Naming Convention Dilemma
One initial concern is the requirement that all Hooks begin with the prefix "use." While this guideline is logical and helps differentiate Hooks from standard functions, it can lead to awkward naming conventions. For instance, names like useAddToCart and useFetchPosts may sound grammatically incorrect or awkward.
Section 1.2: The Order of Hook Calls
According to the official documentation, one of the key rules for using Hooks is:
- Only invoke Hooks at the top level. Avoid calling Hooks within loops, conditions, or nested functions.
This rule allows for straightforward code, such as:
const [name, setName] = useState('bytefish');
const [age, setAge] = useState(30);
const [job, setJob] = useState('frontend dev');
However, it prohibits structures like:
const [name, setName] = useState('bytefish');
if (Math.random() > 0.5) {
const [age, setAge] = useState(30);
const [job, setJob] = useState('frontend dev');
}
Why is this rule necessary? React manages component states in an array, and each re-render reads this array in sequence. If the sequence of useState calls varies between renders, it can result in mismatched variables and states.
The ordering issue is illustrated as follows:
During a subsequent render, if the order has changed due to conditional logic, it can lead to significant errors:
Live Demo:
The first video titled "What are React Hooks - Functional Components" gives a foundational understanding of React Hooks, which can help clarify their usage and potential pitfalls.
Section 1.3: The Confusing Nature of useEffect
Typically, useEffect is utilized as follows:
const [value] = useState(0);
React.useEffect(() => {
console.log("Effect executed");
}, [value]);
This effect triggers whenever the value changes. However, consider this alternative implementation:
function App() {
React.useEffect(() => {
console.log("Effect executed");}, [Date.now()]);
return <div>...</div>;
}
You might assume this effect will execute frequently since Date.now() changes constantly. Surprisingly, it only runs once upon the initial render. The reason lies in a hidden rule: effects only trigger upon re-renders.
If you modify the component to include a state variable that changes, the behavior shifts dramatically:
Live Demo:
The second video, "Why You Need Hooks and Project," provides insight into practical applications of Hooks, which may further illustrate their complexities.
Section 1.4: useEffect vs. componentDidMount
To fetch data from a server after a component mounts, many developers might write:
const [data, setData] = useState(null);
function fetchData() {
console.log('Fetching data from server');
setData({ data: 'data from server' });
}
fetchData();
However, this leads to repeated executions of fetchData. To address this, we can use useEffect:
useEffect(() => {
fetchData();
}, []);
Yet, this approach can be problematic in complex component trees where componentDidMount might trigger too late, delaying data fetching.
In tests, I found that effects could wait up to 200 milliseconds to execute:
In intricate rendering scenarios, the delay may increase further. Utilizing useRef can alleviate this issue, enabling quicker data requests without repetition.
Ultimately, while useEffect aims to monitor changes and lifecycle events, its design can lead to confusion as it intertwines the two concepts.
Final Thoughts
This discussion is not intended as a critique of React Hooks. They possess numerous strong design elements, and I continue to use them extensively in my projects. My goal is to highlight certain issues within Hooks, allowing for more informed and rational usage.