Solving Critical Frontend Issues in a React + Rails ERP System

Solving Critical Frontend Issues in a React + Rails ERP System

How I Fixed Four Show-Stopping Bugs in Production

Working on a large-scale ERP system with React and Rails, I encountered several critical frontend issues that completely blocked user access. Here's how I systematically diagnosed and resolved each problem.

Issue 1: The Blank Page Mystery - MUI X TreeView Import Error

The Problem

Users were greeted with a completely blank page when accessing the application. The browser console revealed:

Uncaught SyntaxError: The requested module '@mui/x-tree-view' 
does not provide an export named 'TreeView'

Investigation Process

First, I checked the installed MUI versions:

cd erp-frontend
npm ls @mui/x-tree-view
# Output: @mui/x-tree-view@8.10.0

Then I examined the problematic import:

sed -n '30p' src/pages/hr/Departments.tsx
# Output: import { TreeView, TreeItem } from '@mui/x-tree-view';

The Root Cause

MUI X v8 changed its export structure. Components are no longer available through barrel exports and require specific import paths.

The Solution

I updated the imports to use the correct paths for MUI X v8:

// Before (incorrect for v8)
import { TreeView, TreeItem } from '@mui/x-tree-view';

// After (correct for v8)
import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
import { TreeItem } from '@mui/x-tree-view/TreeItem';

I also updated the component usage:

// Changed from <TreeView> to <SimpleTreeView>
<SimpleTreeView
  aria-label="department hierarchy"
  defaultCollapseIcon={<ExpandMoreIcon />}
  defaultExpandIcon={<ChevronRightIcon />}
  expanded={expanded}
  selected={selected}
  onNodeToggle={handleToggle}
  onNodeSelect={handleSelect}
>
  {renderTree(departmentTree)}
</SimpleTreeView>

Issue 2: X-Frame-Options Console Warning

The Problem

The browser console showed a persistent warning:

X-Frame-Options may only be set via an HTTP header sent along with a document. 
It may not be set inside <meta>.

Investigation

I searched for the offending meta tag:

grep -n "X-Frame-Options" index.html
# Output: 12: <meta http-equiv="X-Frame-Options" content="DENY">

The Solution

X-Frame-Options is a response header, not an HTML meta tag directive. I removed the invalid meta tag:

<!-- Before -->
<meta http-equiv="X-Frame-Options" content="DENY">

<!-- After -->
<!-- X-Frame-Options should be set via HTTP headers, not meta tags -->

This security header should be configured at the server level, not in HTML.

Issue 3: Content Security Policy Blocking API Calls

The Problem

After fixing the rendering issues, the login form appeared but authentication failed with:

Refused to connect to 'http://localhost:3002/api/v1/auth/login' 
because it violates the following Content Security Policy directive: 
"connect-src 'self' http://localhost:3000 ws://localhost:3000..."

Investigation Process

I traced the CSP configuration through the codebase:

# Find CSP definitions
grep -r "connect-src" src/ --include="*.ts"
# Output: src/security/csp.ts: 'connect-src': [...]

Examining the CSP file revealed the issue - port 3002 wasn't whitelisted:

// src/security/csp.ts (before)
'connect-src': [
  "'self'",
  'http://localhost:3000',
  'ws://localhost:3000',
  'http://localhost:8080',
  'ws://localhost:8080',
]

The Solution

I updated the CSP to include the correct ports:

// src/security/csp.ts (after)
'connect-src': [
  "'self'",
  'http://localhost:3002',  // Rails API port
  'ws://localhost:3002',     // WebSocket for Rails
  'http://localhost:3003',   // Frontend dev server
  'ws://localhost:3003',     // WebSocket for Vite HMR
  'http://localhost:3000',   // Legacy support
  'ws://localhost:3000',
  'http://localhost:8080',
  'ws://localhost:8080',
]

Issue 4: Incorrect API URL Configuration

The Problem

Even with CSP fixed, the frontend was still trying to connect to the wrong port.

Investigation

I checked the API configuration:

grep -r "API_URL" src/config/
# Found in src/config/env.ts

The default API URL was pointing to port 3000 instead of 3002:

// Before
API_URL: getEnvVar('VITE_API_URL', 'http://localhost:3000/api/v1'),

The Solution

I updated the configuration to use the correct port:

// src/config/env.ts
export const env = {
  API_URL: getEnvVar('VITE_API_URL', 'http://localhost:3002/api/v1'),
  WEBSOCKET_URL: getEnvVar('VITE_WEBSOCKET_URL', 'ws://localhost:3002/cable'),
  // ... rest of config
};

And added environment variable for explicit configuration:

echo "VITE_API_URL=http://localhost:3002/api/v1" >> .env.local

Final Verification Steps

After applying all fixes, I performed a complete restart and verification:

# Clear Vite cache
rm -rf node_modules/.vite

# Restart the development server
npm run dev

# Verify the Rails API is responding
curl http://localhost:3002/up
# Output: <!DOCTYPE html><html><body style="background-color: green"></body></html>

# Test authentication endpoint
curl -X POST http://localhost:3002/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@pcvn.com","password":"password123"}'
# Output: HTTP/1.1 200 OK (with JWT token in response)

Key Takeaways

MUI X v8 Breaking Changes: Always check the migration guide when upgrading major versions. The shift from barrel exports to specific import paths caught many developers off guard.

Security Headers: X-Frame-Options, CSP, and other security headers belong in server responses, not HTML meta tags. Understanding the distinction prevents console warnings and potential security issues.

Content Security Policy: When developing locally with multiple services on different ports, ensure your CSP whitelist includes all necessary endpoints. This is especially important in microservices architectures.

Environment Configuration: Centralizing API URLs in a configuration file makes it easier to manage different environments and prevents hardcoded values scattered throughout the codebase.

Preventing Future Issues

To avoid similar problems in the future, I implemented several best practices:

Documentation: Added clear notes about MUI import requirements and CSP configuration to the project documentation.

Environment Templates: Created .env.example files with all required variables clearly documented.

Automated Checks: Consider adding a pre-commit hook to validate import statements and CSP configurations.


These fixes transformed a completely broken frontend into a fully functional application, allowing the team to continue development and users to access the system without issues.

Have you encountered similar issues in your React projects? I'd love to hear about your experiences and solutions in the comments.


If you enjoyed this article, you can also find it published on LinkedIn and Medium.