Deadly Mistakes to Avoid When Using React
Tech News

10 Deadly Mistakes to Avoid When Using React in 2023

React has quickly become one of the most popular JavaScript libraries for building user interfaces. Its declarative nature, component-based architecture and ability to rapidly render updates makes it a go-to choice for many developers. However, React’s flexibility and lack of opinionation means it’s easy to pick up bad habits that will come back to bite you later. Here are 10 deadly mistakes to avoid when using React if you want to build high-quality, maintainable applications.

1. Not Using Fragments When Returning Multiple Elements

When returning multiple adjacent JSX elements, your first instinct might be to wrap them in a <div>:

return ( <div> <ChildA /> <ChildB /> </div> );

While valid, this leads to unnecessary nested <div>s in your rendered HTML.

A better solution is to use React’s Fragment component:

return ( <Fragment> <ChildA /> <ChildB /> </Fragment> );

This avoids adding extra nodes to the DOM, keeping your markup clean and semantically correct.

Using Index as Key for Map

2. Using Index as Key for Map

When rendering a list of elements from an array, you need to add a key prop to help React identify items uniquely:

const listItems = data.map((item, index) => <li key={index}>…</li> );

It’s tempting to just use the index as a key, but this can lead to poor performance and bugs for dynamic lists.

Instead, use a stable, unique identifier if available:

const listItems = data.map(item => <li key={item.id}>{item.name}</li> );

If no ID exists, generate a unique key like {item.type + item.index}.

3. Forgetting to Call Hooks at Top Level

React Hooks like useState and useEffect cannot be called conditionally or in loops – they must always be invoked at the top level of a component:

Wrong:

if (user) { const [name, setName] = useState(user.name); }

Correct:

const [name, setName] = useState(user.name); if (user) { // use name & setName }

Follow this rule to avoid very confusing bugs!

4. Spreading Props on DOM Elements

When passing props to DOM components like <div> or <input>, you may be tempted to spread the props object:

return <input {…props} />;

However, this can pass invalid HTML attributes and attributes that conflict with React’s usage like key.

Explicitly list allowed props instead:

const { disabled, value, …inputProps } = props; return ( <input disabled={disabled} value={value} {…inputProps} /> );

This prevents invalid props being passed down.

5. Fetching Data Inside useEffect Without Dependencies

When fetching data from an API inside a useEffect hook, it’s important to add the dependencies as an array second argument:

Wrong:

useEffect(() => { fetchData(); });

This creates an infinite loop since useEffect runs after every render.

Correct:

useEffect(() => { fetchData(); }, []); // Empty dependency array

This tells React to only run once after initial render, avoiding loops.

6. Neglecting to Clean Up Subscriptions and Timers

If you set up any subscriptions or intervals inside useEffect, don’t forget to clean them up:

useEffect(() => { const id = setInterval(() => { // … }, 1000); return () => clearInterval(id); }, []);

This avoids memory leaks or multiple concurrent intervals/subscriptions.

Similarly, clean up manually tracked event listeners, live query observers etc.

7. Passing Inline Functions to Children

It’s handy to pass callback functions to child components:

<Child onClick={() => console.log(‘Clicked!’)} />

However, this creates a new function instance on every parent re-render.

Instead, declare it outside to avoid performance issues:

const handleClick = () => { console.log(‘Clicked!’); } <Child onClick={handleClick} />

Now the function won’t change identity between renders.

Using Index as Key for Map

8. Failing to Batch State Updates

When updating state based on previous state, batch the updates together:

Wrong:

setCount(count + 1); setFlag(true);

This causes two renders instead of one.

Correct:

setCount(prevCount => prevCount + 1); setFlag(true);

React will batch these into a single update.

You can also use a functional setState parameter for this.setState.

9. Unnecessary Re-Renders from Props

React re-renders by default when a parent component passes new props.

Sometimes you only care about certain props changing. In this case, implement shouldComponentUpdate:

class Child extends React.Component { shouldComponentUpdate(nextProps) { // Only re-render if props.foo changes return this.props.foo !== nextProps.foo; } render() { // … } }

Or with function components, React.memo for a similar effect:

const Child = React.memo(props => { // Render });

This avoids wasted re-rendering if certain props are unchanged.

10. Using React setState Like a jQuery Trigger

setState shouldn’t be called every time something changes – typically data flows down the component tree.

Avoid misusing setState as a way to “trigger” updates across your app:

Wrong:

// Menu component this.props.onMenuOpenChanged(true); // Parent component onMenuOpenChanged(isOpen) { this.setState({menuIsOpen: isOpen}); // Causes render }

It’s better to directly pass isOpen as a prop and let Parent control its own state.

Only use setState on the component needing to update.

Key Takeaways

  • Use Fragments to avoid unnecessary DOM nodes from wrapping elements.
  • Give list items stable, unique keys like IDs to avoid issues.
  • Call Hooks unconditionally at top level.
  • Avoid spreading props on DOM elements.
  • Add dependencies to useEffect to prevent infinite loops.
  • Clean up subscriptions, timers and other side effects properly.
  • Declare inline event handlers outside components to prevent recreates.
  • Batch multiple state updates together when possible.
  • Implement shouldComponentUpdate to prevent unnecessary re-renders.
  • Don’t overuse setState – let data flow down the component tree.

Following these best practices will help you avoid many common pitfalls when writing React applications. Your components will be more optimized, robust and declarative in nature.

Frequently Asked Questions

Q: What is the best way to fetch data in React?

A: The recommended approach is to fetch data in a useEffect hook and store it in state. Be sure to add dependencies to avoid infinite loops.

Q: Should I use React classes or functional components?

A: Functional components with Hooks are recommended for most use cases now. But classes still have valid use cases like error boundaries.

Q: How do I prevent components from re-rendering unnecessarily?

A: Implement React.memo on functional components or shouldComponentUpdate in classes to control when re-renders occur.

Q: What is the difference between state and props in React?

A: State is internal and controlled by the component. Props are external and passed from parent components. Components can’t modify their own props.

Q: How do I style components in React?

A: Recommended options are CSS Modules, Styled Components and CSS-in-JS libraries like Emotion. Avoid importing global .css files.

Conclusion

React is a highly valuable tool for creating user interfaces, but it requires careful attention to avoid common mistakes. By following a set of best practices, you can ensure that your applications are both scalable and efficient. ML Observability is crucial for ensuring your model’s performance remains optimal. Just as in React development where proper structuring, cautious handling of effects, and optimization are vital, tracking key metrics in machine learning offers similar insights, allowing you to implement best practices and leverage community lessons for sustained model excellence. ML observability is crucial for tracking your model’s performance, much like the importance of properly structuring components, being cautious with effects, optimizing rendering behavior, and keeping state encapsulated in React development. These key ideas ensure not only robust machine learning monitoring but also expert-level proficiency in building scalable and efficient projects.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.