Overview
The SSEGH Security Cameras application follows a component-based React architecture with Redux Toolkit for state management. The application uses React Router for client-side routing via HashRouter, allowing static deployment without server-side configuration.
Project Structure
The application is organized into distinct directories, each serving a specific purpose:
source/
├── app.js # Application entry point
├── components/ # React components
│ ├── main.js # Main products page
│ ├── principal.js # Landing page
│ ├── navbarTop.js # Top navigation
│ ├── navbarAside.js # Sidebar filters
│ ├── listcam.js # Camera list display
│ ├── cardscamara.js # Camera card component
│ ├── viewcamera.js # Individual camera view
│ ├── filtercamaras.js # Filtered results
│ ├── contacto.js # Contact page
│ ├── nosotros.js # About page
│ ├── notfound.js # 404 page
│ ├── onload.js # Loading component
│ └── whatsappIcon.js # WhatsApp integration
├── store/ # Redux state management
│ ├── store.js # Store configuration
│ └── camarasSlice.js # Camera data slice
├── services/ # External services
│ └── getdata.js # Data fetching
├── utilities/ # Helper functions
│ ├── const.js # Constants and imports
│ ├── filterdata.js # Filter utilities
│ └── otherFunctions.js # Utility functions
└── static/ # Static assets
├── estilos.css
└── images/
Component Hierarchy
The application follows a hierarchical component structure that flows from the root App component:
Root Level
The App component serves as the application root, wrapped in Redux Provider and React Router. const root = ReactDOM . createRoot ( document . getElementById ( "root" ))
root . render (
< React.StrictMode >
< Provider store = { store } >
< App />
</ Provider >
</ React.StrictMode >
)
Router Level
The App component initializes state and renders the HashRouter with NavbarTop and Routes. return (
data ?
< HashRouter basename = "/" >
< NavbarTop />
< Routes >
< Route path = "/" element = { < Principal /> } ></ Route >
< Route path = "/productos" element = { < Main /> } ></ Route >
< Route path = "/nosotros" element = { < Nosotros /> } ></ Route >
< Route path = "/contacto" element = { < Contacto /> } ></ Route >
< Route path = "*" element = { < NotFound /> } ></ Route >
< Route path = "/productos/camaras/:modelo" element = { < ViewCamera /> } ></ Route >
< Route path = "/productos/camaras/filtro/:filter" element = { < FilterCamara /> } ></ Route >
</ Routes >
</ HashRouter >
: < OnLoad />
)
Page Level
Each route renders a page component (Principal, Main, Nosotros, Contacto) that manages its layout.
Feature Components
Page components compose smaller feature components like NavbarAside, ListCam, and CardsCamara. return (
< div className = "col-12" >
< div className = "container" >
< div className = "row" >
< NavbarAside camaras = { data } />
< ListCam camaras = { data } />
< WhatsappIcon />
</ div >
</ div >
</ div >
)
Architectural Patterns
Container/Presentation Pattern
The application separates container components (that manage state) from presentational components (that render UI):
Container components : Main, ViewCamera, FilterCamara connect to Redux and manage data flow
Presentation components : CardsCamara, ListCam, NavbarOptionsTop receive props and render UI
State Management Architecture
The application uses Redux Toolkit for centralized state management:
const { configureStore } = RTK
const store = configureStore ({
reducer: {
camaras: camarasSlice . reducer
}
})
All camera data and filtering logic lives in the Redux store, accessible to any component via useSelector and useDispatch hooks.
UMD Module Pattern
The application loads React, Redux, and React Router as UMD (Universal Module Definition) modules via CDN:
< script src = "https://unpkg.com/[email protected] /umd/react.development.js" ></ script >
< script src = "https://unpkg.com/[email protected] /umd/react-dom.development.js" ></ script >
< script src = "https://unpkg.com/@babel/standalone/babel.min.js" ></ script >
< script src = "https://unpkg.com/[email protected] /dist/umd/react-router-dom.development.js" ></ script >
< script src = "https://unpkg.com/[email protected] /dist/react-redux.min.js" ></ script >
< script src = "https://unpkg.com/@reduxjs/[email protected] /dist/redux-toolkit.umd.js" ></ script >
This architecture allows the application to run without a build step, making it easy to deploy as static files.
Data Flow
The application follows unidirectional data flow:
Initialization
Camera data is defined in camarasSlice.js as initialState and loaded into the store.
Component Access
Components access state using the useSelector hook: const data = useSelector (( state ) => state . camaras )
State Updates
User interactions trigger actions via useDispatch: useEffect (() => {
dispatch ( backToInitialState ( 'reset' ))
}, [ dispatch ])
Reducer Processing
Reducers in camarasSlice process actions and return updated state, triggering component re-renders.
File Organization Principles
Components Directory
Components are organized by feature and page:
Navigation components : navbarTop.js, navbarAside.js
Product display : listcam.js, cardscamara.js, viewcamera.js
Pages : principal.js, contacto.js, nosotros.js
Utilities : onload.js, notfound.js, whatsappIcon.js
Constants and Configuration
The utilities/const.js file centralizes imports and constants:
const ITEMS_NAV_TOP = [ "Productos" , "Nosotros" , "Contacto" ]
const FIELDS_CARD = [ "diseño" , "resolucion" , "conectividad" , "marca" , "tipo_de_camara" ]
const Routes = ReactRouterDOM . Routes
const Route = ReactRouterDOM . Route
const BrowserRouter = ReactRouterDOM . BrowserRouter
const Link = ReactRouterDOM . Link
const Navigate = ReactRouterDOM . Navigate
const HashRouter = ReactRouterDOM . HashRouter
const useLocation = ReactRouterDOM . useLocation
const useNavigate = ReactRouterDOM . useNavigate
const useParams = ReactRouterDOM . useParams
This centralized approach makes it easy to update library references and shared constants across the application.
Loading Strategy
The application implements a loading state to ensure data is available before rendering:
const App = () => {
const { useState , useEffect } = React ;
const [ data , setData ] = useState ( null )
const { useSelector } = ReactRedux
const camaras = useSelector (( state ) => state . camaras )
useEffect (() => {
setData ( camaras )
}, [])
return ( data ? < HashRouter > ... </ HashRouter > : < OnLoad /> )
}
This ensures users see a loading indicator until the application is ready to display content.
Next Steps
Routing Learn how React Router manages navigation and dynamic routes
State Management Explore Redux Toolkit configuration and state flow