DocumentationReact

React

Mount a model with the optional React binding.

Mount the components

Live2DCanvas owns rendering; Live2DModel owns loading and cleans up when React unmounts it.

tsx
import { Live2DCanvas, Live2DModel } from 'live2d-web/react'
 
export function Avatar() {
  return (
    <Live2DCanvas coreUrl="/live2dcubismcore.min.js">
      <Live2DModel src="/models/model.model3.json" />
    </Live2DCanvas>
  )
}

More than one model

A canvas takes as many models as you give it. They share its WebGL context, so a second character does not spend one of the few a browser allows.

Duo.tsx
<Live2DCanvas coreUrl="/live2dcubismcore.min.js">
  <Live2DModel src="/models/host.model3.json" fit="full" />
  <Live2DModel
    src="/models/guest.model3.json"
    fit={{ scale: 0.8, offsetX: 0.3, units: 'stage' }}
  />
</Live2DCanvas>

They draw in the order they appear, so a later one sits on top. Each carries its own fit, followPointer and onTap, and a <LipSync> or tracking child attaches to the model it sits under. Unmounting one leaves the canvas and the others alone.

paused belongs to the canvas: <Live2DCanvas paused> stops the whole thing. It still works on a model, where any paused model pauses the canvas.

Canvas accessibility

Describe a meaningful character as an image, or hide a purely decorative one. The library does not make the Canvas keyboard-focusable; provide ordinary DOM buttons for tap or motion actions and reduce their animation when prefers-reduced-motion is enabled.

tsx
<Live2DCanvas
  accessibility={{
    label: 'Animated support character',
    describedBy: 'avatar-help',
  }}
  coreUrl="/live2dcubismcore.min.js"
>
  <Live2DModel src="/models/model.model3.json" />
</Live2DCanvas>
 
<p id="avatar-help">The character reacts to the motion buttons below.</p>
<button type="button" onClick={() => controller?.motion('TapBody', 0)}>
  Play greeting
</button>

Use accessibility={{ mode: 'decorative' }} when the Canvas adds no information.

Use the controller after readiness

Receive the model controller from the component API used by your view and keep commands in event handlers. Do not issue a motion during Server Component rendering or assume the controller exists before the model reports ready. A controller becomes invalid after its model unmounts.

tsx
import { useLive2DModel } from 'live2d-web/react'
 
function MotionButton() {
  const controller = useLive2DModel()
  return (
    <button disabled={!controller} onClick={() => controller?.motion('TapBody', 0)}>
      Play greeting
    </button>
  )
}
 
<Live2DModel src="/models/model.model3.json">
  <MotionButton />
</Live2DModel>

Strict Mode, retry and cleanup

React development Strict Mode may mount, clean up and mount again. Let Live2DCanvas and Live2DModel own their resources instead of caching a controller globally. Keep accessibility and model options value-stable when possible; changing meaningful Stage options intentionally recreates the Stage, while equivalent inline accessibility values do not.