React hooks and utilities for FiveM NUI development.
npm install fivem-nui-react// Listen for NUI messages from FiveM client
useNuiEvent("eventName", (data) => {});
// Send request and get response
const data = await fetchNui("eventName", { payload });
// Hook with loading/error states and callback
const [fetch, { loading, error }] = useNuiCallback("eventName", (data) => {});
// Send data without expecting response
const [send, { loading, error }] = useSendNui("eventName");
// Check if running in browser (debug mode)
if (isEnvBrowser())-- Send message from FiveM client to UI
SendNUIMessage({ action = "eventName", data = { key = "value" } })
-- Register callback for UI requests
RegisterNUICallback("eventName", function(data, cb)
cb({ response = "data" })
end)Listen for NUI messages sent from FiveM client.
useNuiEvent<T>(
action: string,
handler: (data: T) => void,
options?: { mockData?: T; mockDelay?: number }
): voidExample:
import { useNuiEvent } from "fivem-nui-react";
function App() {
const [visible, setVisible] = useState(false);
useNuiEvent<{ show: boolean }>("toggleUI", (data) => setVisible(data.show), {
mockData: { show: true },
mockDelay: 1000,
});
return visible ? <div>UI Content</div> : null;
}FiveM Client (Lua):
SendNUIMessage({
action = "toggleUI",
data = { show = true }
})Send a request to the FiveM client and receive a response.
fetchNui<T, D>(
eventName: string,
data?: D,
options?: { mockData?: T; mockDelay?: number; signal?: AbortSignal }
): Promise<T>Example:
import { fetchNui } from "fivem-nui-react";
const player = await fetchNui<PlayerData>(
"getPlayerData",
{ id: 1 },
{
mockData: { name: "John", level: 10 },
mockDelay: 500,
},
);With AbortController:
const controller = new AbortController();
const player = await fetchNui<PlayerData>(
"getPlayerData",
{ id: 1 },
{
signal: controller.signal,
},
);
// Cancel the request
controller.abort();FiveM Client (Lua):
RegisterNUICallback("getPlayerData", function(data, cb)
local playerId = data.id
cb({ name = "John", level = 10 })
end)Hook for NUI requests with loading/error states. Calls the callback with response data.
useNuiCallback<T, D>(
eventName: string,
callback: (data: T) => void,
options?: { mockData?: T; mockDelay?: number }
): [(data?: D) => Promise<T>, { loading: boolean; error: Error | null }]Example:
import { useNuiCallback } from "fivem-nui-react";
function PlayerInfo() {
const [player, setPlayer] = useState<PlayerData | null>(null);
const [fetchPlayer, { loading, error }] = useNuiCallback<PlayerData>(
"getPlayerData",
(data) => setPlayer(data),
{ mockData: { name: "John", level: 10 }, mockDelay: 500 },
);
useEffect(() => {
fetchPlayer({ id: 1 });
}, [fetchPlayer]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{player?.name}</div>;
}FiveM Client (Lua):
RegisterNUICallback("getPlayerData", function(data, cb)
local playerId = data.id
cb({ name = "John", level = 10 })
end)Hook for sending data to FiveM client without expecting a response.
useSendNui<D>(
eventName: string,
options?: { mockDelay?: number }
): [(data?: D) => Promise<void>, { loading: boolean; error: Error | null }]Example:
import { useSendNui } from "fivem-nui-react";
function CloseButton() {
const [closeUI, { loading }] = useSendNui<{ reason: string }>("closeUI");
return (
<button
onClick={() => closeUI({ reason: "user_clicked" })}
disabled={loading}
>
Close
</button>
);
}FiveM Client (Lua):
RegisterNUICallback("closeUI", function(data, cb)
SetNuiFocus(false, false)
cb("ok")
end)Check if running in browser (outside FiveM).
import { isEnvBrowser } from "fivem-nui-react";
if (isEnvBrowser()) {
console.log("Running in browser - debug mode");
}All hooks support mock data for testing in browser without FiveM:
| Option | Description | Default |
|---|---|---|
mockData |
Data to return in browser mode | - |
mockDelay |
Delay in ms before returning | 500 |
signal |
AbortSignal for request cancellation (fetchNui only) |
- |
When isEnvBrowser() is true:
useNuiEventtriggers handler withmockDataafter delayfetchNuireturnsmockDataafter delayuseNuiCallbackcalls callback withmockDataafter delayuseSendNuisimulates delay only
All functions are fully typed:
interface PlayerData {
name: string;
level: number;
}
interface PlayerRequest {
id: number;
}
// Typed response
const player = await fetchNui<PlayerData, PlayerRequest>("getPlayer", {
id: 1,
});
// Typed callback
const [fetchPlayer, { loading }] = useNuiCallback<PlayerData, PlayerRequest>(
"getPlayer",
(data) => console.log(data.name),
);Most of the code in this project was written by AI and then manually reviewed and edited.
MIT