Your React App Isn’t Great — Fix It With Controllers.

Your React App Isn’t Great — Fix It With Controllers.Leverage the Power of Controllers and Make Your React Apps Invincible.Photo by Bobby Mc Leod on UnsplashAs your colleagues struggled with debugging overly coupled code, I shared some tips to help you…


This content originally appeared on Level Up Coding - Medium and was authored by Pierre G.

Your React App Isn’t Great — Fix It With Controllers.

Leverage the Power of Controllers and Make Your React Apps Invincible.

Photo by Bobby Mc Leod on Unsplash

As your colleagues struggled with debugging overly coupled code, I shared some tips to help you create React apps they’ll love (read this through if you haven’t yet). I hope you’re not too overwhelmed with congratulations and romantic messages — great code, after all, can evoke strong emotions.

Technical Discovery

Let’s explore controllers a bit further through a classic example of a frontend application — you guessed it: the To-Do List 📝. Keep it simple.

My Todo is a stateful application that stores items through a REST API.

So far, nothing extraordinary. How about we break down the UI into view components?

Simple UI breakdown.

Here we are. Now that we have a clear breakdown of the UI, we need to define controllers and their responsibilities — basically, what interfaces will be exposed to the view components (and other controllers).

Controllers and their dependencies.
  • ErrorController [stateful]: Handles the error state — a simple string visible by end users. Most controllers depend on it.
  • CreateItem [stateful]: Handles changes made by end users through the form. It also makes API calls to create a new item—that's why it depends on the API client.
  • ListItems [stateful]: Fetches the items of the current user and stores them in a React state. It exposes a refresh() function that the CreateItem controller uses to update items after a successful creation.
  • DeleteItem [stateless]: Handles clicks on delete buttons.

On top of these controllers:

  • A simple sanitizer that allows for removing extra characters, like spaces at the start and end of input strings. To ease unit testing, it is isolated in a dedicated module.
  • An API client exposing asynchronous functions to create, read, and delete To-Do items.

Note: If you plan to create a real Todo for real users (and aim for lofty ambitions with it), you should also add a loader. To keep the example concise, I’ve skipped it, but the principle remains the same.
You could also add validators with feedback messages while the user is typing, along with all sorts of lovely features to improve the UX.

This approach strongly decouples the UI frame from the controlling logic. You’ll be able to update views by extracting DOM nodes and inserting new components as much as you want, without even thinking about how to access data and handle user actions. Consequently, connecting views with data becomes an easy game 💪.
Additionally, testing the controlling logic separately from the UI presents significant benefits by reducing the complexity of unit tests.

Implementation

Ok, we now have a clear overview of how to implement our app: it’s time to code.

Let’s dive into the CreateItem controller. How will it look?

import React, { createContext, useContext, useState, ReactNode } from 'react'
import { useErrorController } from './errorController'
import { todoClient } from '../clients/todo'
import { sanitizeFormInput } from '../sanitizers/strings'


interface CreateItemType {
onChange: (itemValue: string) => void
createItem: () => Promise<void>
}

interface CreateItemProviderProps {
children: ReactNode
}

const CreateItem = createContext<CreateItemType | null>(null)

export const CreateItemProvider: React.FC<CreateItemProviderProps> = ({
children,
}) => {
const { displayError } = useErrorController()

const [itemValue, setItemValue] = useState<string>('')

const createItem = async () => {
try {
const sanitizedValue = sanitizeFormInput(itemValue)
await todoClient.createItem(sanitizedValue)
} catch (err) {
displayError(err)
}
}

const onChange = (value: string) {
setItemValue(value)
}

const value: CreateItemType = {
createItem,
onChange
}

return (
<CreateItem.Provider value={value}>
{children}
</CreateItem.Provider>
)
}

export const useCreateItem = (): CreateItemType => {
const context = useContext(CreateItem)
if (!context) {
throw new Error('useCreateItem must be used within a CreateItemProvider')
}
return context
}

The file createItem.tsx contains:

  • A React context provider, CreateItemProvider which embeds the controlling logic and exposes the controller interface, i.e., two functions: onChange(), which updates the state of the form input, and createItem(), which triggers API calls.
  • A React hook,useCreateItem(), eases access to the context. It can be consumed as follows within view components (or other controllers):
const Form = () => {
const { onChange, createItem } = useCreateItem()
// View component logic
}

How to connect view components with controllers?

For a given view component to consume a given controller, the view component must be a child of the controller provider.
To clarify dependencies and ease data access, I recommend instantiating all controller providers within the same file at the top of the page. This way, controllers can be accessed by any view component.
Ultimately, if you face performance issues, you can adjust the approach and refine the hierarchy.

const TodoApp = () => {
// Mount controllers providers to make them accessible from
// any view component.
// Page is the root of view components.
return (
<ErrorController>
<ListItems>
<CreateItem>
<DeleteItem>
<Page />
</DeleteItem>
</CreateItem>
</ListItems>
</ErrorController>
)
}

Important note: when calling providers ensure the order matches the dependencies between controllers.

And that’s it! This is a way to build robust controllers with React native tools. I hope you enjoyed this article. Let me know if you’d like to dive deeper into certain aspects.
Thanks for reading!


Your React App Isn’t Great — Fix It With Controllers. was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Pierre G.


Print Share Comment Cite Upload Translate Updates
APA

Pierre G. | Sciencx (2025-01-19T20:28:25+00:00) Your React App Isn’t Great — Fix It With Controllers.. Retrieved from https://www.scien.cx/2025/01/19/your-react-app-isnt-great-fix-it-with-controllers/

MLA
" » Your React App Isn’t Great — Fix It With Controllers.." Pierre G. | Sciencx - Sunday January 19, 2025, https://www.scien.cx/2025/01/19/your-react-app-isnt-great-fix-it-with-controllers/
HARVARD
Pierre G. | Sciencx Sunday January 19, 2025 » Your React App Isn’t Great — Fix It With Controllers.., viewed ,<https://www.scien.cx/2025/01/19/your-react-app-isnt-great-fix-it-with-controllers/>
VANCOUVER
Pierre G. | Sciencx - » Your React App Isn’t Great — Fix It With Controllers.. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/01/19/your-react-app-isnt-great-fix-it-with-controllers/
CHICAGO
" » Your React App Isn’t Great — Fix It With Controllers.." Pierre G. | Sciencx - Accessed . https://www.scien.cx/2025/01/19/your-react-app-isnt-great-fix-it-with-controllers/
IEEE
" » Your React App Isn’t Great — Fix It With Controllers.." Pierre G. | Sciencx [Online]. Available: https://www.scien.cx/2025/01/19/your-react-app-isnt-great-fix-it-with-controllers/. [Accessed: ]
rf:citation
» Your React App Isn’t Great — Fix It With Controllers. | Pierre G. | Sciencx | https://www.scien.cx/2025/01/19/your-react-app-isnt-great-fix-it-with-controllers/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.