Explorer
KNOW-PAT-090

FiveM - React NUI Banking : state management, hash generation, currency format

Domaine
web-uiux
Type
pattern
Priorité
P2

Parent : [[INDEX-WEB-UIUX]]

FiveM - React NUI Banking : state management, hash generation, currency format

Problème

Les UI FiveM traditionnelles utilisent du HTML vanilla avec jQuery. Une UI bancaire complexe (transferts, historique, cartes) nécessite un framework frontend moderne pour le state management et la réactivité.

Solution

Application React dans NUI FiveM avec hooks useState/useEffect, génération de numéros de carte basée sur hash, formatage currency, et communication via window.invokeNative / fetchNui.

// Génération de numéro de carte basée sur un seed (identifiant joueur)
const generateCardNumber = (seed = '') => {
    let hash = 0;
    for (let i = 0; i < seed.length; i++) {
        const char = seed.charCodeAt(i);
        hash = ((hash << 5) - hash) + char;
        hash = hash & hash;
    }
    const num = Math.abs(hash) % 10000;
    return num.toString().padStart(4, '0');
};

// Formatage currency
const formatCurrency = (amount, currency = 'USD') => {
    return new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: currency
    }).format(amount);
};

// Fetch NUI helper
const fetchNui = async (eventName, data) => {
    const resourceName = window.GetParentResourceName?.() || 'nui-frame';
    const resp = await fetch(`https://${resourceName}/${eventName}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
    });
    return await resp.json();
};

// React hook pour les transactions
const useTransactions = () => {
    const [transactions, setTransactions] = useState([]);
    
    useEffect(() => {
        fetchNui('getTransactions', {}).then(setTransactions);
        
        const interval = setInterval(() => {
            fetchNui('getTransactions', {}).then(setTransactions);
        }, 30000);
        
        return () => clearInterval(interval);
    }, []);
    
    return transactions;
};

Pourquoi

  • React offre une UI réactive sans DOM manipulation manuelle
  • Le hash de carte garantit la cohérence visuelle par joueur
  • fetchNui est le standard moderne pour la communication NUI ↔ Lua

Quand l'utiliser

  • UI complexes avec état (inventaire, banking, téléphone, MDT)
  • Interfaces nécessitant listes dynamiques, filtres, pagination

Quand NE PAS l'utiliser

  • UI simples (notification toast, progress bar) → ox_lib suffit
  • Si le bundle React dépasse 500KB et cause des temps de chargement longs

Exemples

Correct

// React component avec NUI event listeners
const BankingApp = () => {
    const [visible, setVisible] = useState(false);
    const [balance, setBalance] = useState(0);
    
    useEffect(() => {
        window.addEventListener('message', (event) => {
            if (event.data.type === 'openBank') {
                setVisible(true);
                setBalance(event.data.balance);
            }
            if (event.data.type === 'closeBank') {
                setVisible(false);
            }
        });
    }, []);
    
    const handleTransfer = async (targetId, amount) => {
        const result = await fetchNui('transferMoney', { targetId, amount });
        if (result.success) {
            setBalance(prev => prev - amount);
        }
    };
    
    return visible ? <BankingUI balance={balance} onTransfer={handleTransfer} /> : null;
};

Incorrect

// Manipulation DOM directe dans NUI (buggy, non-réactive)
document.getElementById('balance').innerText = '$' + data.balance;
document.getElementById('transfer-btn').onclick = function() {
    fetch('https://resource/transfer', { method: 'POST' }); // Pas de async/await
};

Références

  • omes_banking/nui/script.js
  • REF-001 (CFX NUI documentation)