Web APIs
OneJS provides browser-compatible APIs so JavaScript libraries and patterns work as expected. These are implemented using Unity's underlying systems.
localStorage
Persist data using Unity's PlayerPrefs:
// Store data
localStorage.setItem("username", "player1")
localStorage.setItem("settings", JSON.stringify({ volume: 0.8 }))
// Retrieve data
const username = localStorage.getItem("username") // "player1"
const settings = JSON.parse(localStorage.getItem("settings"))
// Remove data
localStorage.removeItem("username")
// Clear all data
localStorage.clear()Limitations
Unlike browser localStorage:
localStorage.key(index)always returnsnull(PlayerPrefs doesn't support enumeration)localStorage.lengthalways returns0- Data persists permanently (no expiration)
Example: Saving Game State
function usePersistentState(key, defaultValue) {
const [value, setValue] = useState(() => {
const stored = localStorage.getItem(key)
return stored ? JSON.parse(stored) : defaultValue
})
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value))
}, [key, value])
return [value, setValue]
}
function Settings() {
const [volume, setVolume] = usePersistentState("volume", 1.0)
return (
<Slider
value={volume}
lowValue={0}
highValue={1}
onChange={(e) => setVolume(e.value)}
/>
)
}sessionStorage
sessionStorage is an alias to localStorage in OneJS. Unity doesn't have browser-style sessions, so data persists across app restarts.
If you need session-scoped data, clear on app start:
// At app initialization
const SESSION_KEY = "__session_id"
const currentSession = Date.now().toString()
const lastSession = localStorage.getItem(SESSION_KEY)
if (lastSession !== currentSession) {
// Clear session data from previous run
localStorage.removeItem("temp_data")
localStorage.setItem(SESSION_KEY, currentSession)
}URL & URLSearchParams
Parse and manipulate URLs:
// Parse a URL
const url = new URL("https://api.example.com:8080/users?page=1&limit=10#section")
console.log(url.hostname) // "api.example.com"
console.log(url.port) // "8080"
console.log(url.pathname) // "/users"
console.log(url.search) // "?page=1&limit=10"
console.log(url.hash) // "#section"
console.log(url.origin) // "https://api.example.com:8080"
// Modify URL
url.pathname = "/posts"
url.searchParams.set("page", "2")
console.log(url.href) // "https://api.example.com:8080/posts?page=2&limit=10#section"URLSearchParams
Work with query strings:
// Create from string
const params = new URLSearchParams("foo=1&bar=2")
// Get values
params.get("foo") // "1"
params.getAll("foo") // ["1"]
params.has("bar") // true
// Modify
params.set("foo", "new")
params.append("baz", "3")
params.delete("bar")
// Iterate
params.forEach((value, key) => {
console.log(`${key}: ${value}`)
})
// Convert to string
params.toString() // "foo=new&baz=3"API Request Helper
function buildApiUrl(endpoint, params = {}) {
const url = new URL(endpoint, "https://api.example.com")
Object.entries(params).forEach(([key, value]) => {
url.searchParams.set(key, value)
})
return url.href
}
// Usage
const url = buildApiUrl("/users", { page: 1, limit: 20 })
// "https://api.example.com/users?page=1&limit=20"Base64 Encoding
Encode and decode Base64:
// Encode string to Base64
const encoded = btoa("Hello, World!")
console.log(encoded) // "SGVsbG8sIFdvcmxkIQ=="
// Decode Base64 to string
const decoded = atob("SGVsbG8sIFdvcmxkIQ==")
console.log(decoded) // "Hello, World!"Use Cases
// Encode JSON for URL-safe transmission
const data = { id: 123, name: "test" }
const encoded = btoa(JSON.stringify(data))
// Basic auth header
const credentials = btoa(`${username}:${password}`)
const headers = { Authorization: `Basic ${credentials}` }Timers
Standard JavaScript timing functions:
// One-time delay
const timeoutId = setTimeout(() => {
console.log("Executed after 1 second")
}, 1000)
clearTimeout(timeoutId) // Cancel
// Repeated interval
const intervalId = setInterval(() => {
console.log("Every 500ms")
}, 500)
clearInterval(intervalId) // Stop
// Immediate execution (microtask)
const immediateId = setImmediate(() => {
console.log("Runs immediately after current code")
})
clearImmediate(immediateId) // Cancel
// Animation frame (synced with Unity Update)
function animate() {
// Update animation
requestAnimationFrame(animate)
}
const rafId = requestAnimationFrame(animate)
cancelAnimationFrame(rafId) // StopReact Timer Patterns
// Interval hook
function useInterval(callback, delay) {
const savedCallback = useRef(callback)
useEffect(() => {
savedCallback.current = callback
}, [callback])
useEffect(() => {
if (delay === null) return
const id = setInterval(() => savedCallback.current(), delay)
return () => clearInterval(id)
}, [delay])
}
// Usage
function Clock() {
const [time, setTime] = useState(new Date())
useInterval(() => {
setTime(new Date())
}, 1000)
return <Label text={time.toLocaleTimeString()} />
}performance.now()
High-precision timestamp for performance measurement:
const start = performance.now()
// Do work
expensiveOperation()
const end = performance.now()
console.log(`Took ${end - start}ms`)Note: In WebGL, this is the native browser API. On other platforms, it returns the time since JavaScript started.
queueMicrotask
Schedule code to run after current task but before rendering:
queueMicrotask(() => {
console.log("Runs after current synchronous code")
})
console.log("This logs first")Useful for batching updates:
let pendingUpdates = []
let scheduled = false
function scheduleUpdate(update) {
pendingUpdates.push(update)
if (!scheduled) {
scheduled = true
queueMicrotask(() => {
const updates = pendingUpdates
pendingUpdates = []
scheduled = false
// Process all batched updates
updates.forEach(u => u())
})
}
}StyleSheet APIs
See Styling - StyleSheet API for runtime stylesheet management (loadStyleSheet, compileStyleSheet, removeStyleSheet, clearStyleSheets).
Platform Differences
| API | Native (QuickJS) | WebGL (Browser) |
|---|---|---|
localStorage | PlayerPrefs | Native localStorage |
fetch | UnityWebRequest | Native fetch |
URL | Polyfill | Native URL |
performance.now() | JS engine time | Native high-res time |
setTimeout | Unity Update loop | Native timers |
requestAnimationFrame | Unity Update loop | Native RAF |