useStore
Hook to access store state and actions with optional selector-based subscriptions
Import
import { useStore } from '@videojs/store/react';Usage
useStore has two overloads:
Without selector — returns the store instance directly. Does NOT subscribe to changes, so the component will not re-render when state changes. Use this to access store actions.
function VolumeControl({ store }) {
const { setVolume } = useStore(store);
return <input type="range" onChange={(e) => setVolume(Number(e.target.value))} />;
}With selector — returns the selected value and subscribes to changes. Re-renders when the selected value changes (using shallow equality by default). You can pass a custom comparator as the third argument.
function TimeDisplay({ store }) {
const currentTime = useStore(store, (s) => s.currentTime);
return <span>{currentTime.toFixed(1)}s</span>;
}Examples
Basic Usage
- Derived State
- Remaining
- 0.0s
- Progress
- 0.0%
Seek Controls
import { createPlayer, features, useStore } from '@videojs/react';
import { Video } from '@videojs/react/video';
import './BasicUsage.css';
const Player = createPlayer({ features: [...features.video] });
function DerivedState() {
const store = Player.usePlayer();
const derived = useStore(store, (s) => ({
remaining: s.duration - s.currentTime,
progress: s.duration > 0 ? (s.currentTime / s.duration) * 100 : 0,
}));
return (
<dl className="react-use-store-basic__derived">
<span className="react-use-store-basic__heading">Derived State</span>
<div>
<dt>Remaining</dt>
<dd>{derived.remaining.toFixed(1)}s</dd>
</div>
<div>
<dt>Progress</dt>
<dd>{derived.progress.toFixed(1)}%</dd>
</div>
</dl>
);
}
function SeekControls() {
const store = Player.usePlayer();
const s = useStore(store);
return (
<div className="react-use-store-basic__seek">
<span className="react-use-store-basic__heading">Seek Controls</span>
<div className="react-use-store-basic__buttons">
<button type="button" onClick={() => s.seek(0)}>
Go to start
</button>
<button type="button" onClick={() => s.seek(s.state.duration / 2)}>
Go to middle
</button>
</div>
</div>
);
}
export default function BasicUsage() {
return (
<Player.Provider>
<Player.Container className="react-use-store-basic">
<Video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoPlay
muted
playsInline
/>
<div className="react-use-store-basic__panel">
<DerivedState />
<SeekControls />
</div>
</Player.Container>
</Player.Provider>
);
}
.react-use-store-basic {
position: relative;
}
.react-use-store-basic video {
width: 100%;
}
.react-use-store-basic__panel {
display: flex;
gap: 16px;
padding: 12px;
background: rgba(0, 0, 0, 0.05);
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.react-use-store-basic__heading {
font-weight: 600;
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: #6b7280;
}
.react-use-store-basic__derived {
display: flex;
flex-direction: column;
gap: 4px;
margin: 0;
font-size: 0.8125rem;
}
.react-use-store-basic__derived div {
display: flex;
gap: 8px;
}
.react-use-store-basic__derived dt {
color: #6b7280;
min-width: 70px;
}
.react-use-store-basic__derived dd {
margin: 0;
font-variant-numeric: tabular-nums;
}
.react-use-store-basic__seek {
display: flex;
flex-direction: column;
gap: 8px;
}
.react-use-store-basic__buttons {
display: flex;
gap: 6px;
}
.react-use-store-basic__buttons button {
padding: 4px 12px;
border-radius: 6px;
border: 1px solid #ccc;
background: white;
cursor: pointer;
font-size: 0.8125rem;
}
API Reference
Overload 1
Access store state and actions.
Without selector: Returns the store, does NOT subscribe to changes. With selector: Returns selected state, re-renders when selected state changes (shallowEqual).
Parameters
| Parameter | Type | Default | |
|---|---|---|---|
store* | AnyStore<any, {}> | — |
Return Value
AnyStore<any, {}>
Overload 2
Parameters
| Parameter | Type | Default | |
|---|---|---|---|
store* | AnyStore<any, {}> | — | |
selector* | Selector<State | any, R> | — | |
isEqual | Comparator<R> | — |
Return Value
R