Hooks
useStore()
Creates an object that Qwik can track across serializations.
Use useStore
to create a state for your application. The returned object is a proxy that has a unique ID that is used in QRL
s to refer to the store.
Example
Example showing how useStore
is used in Counter example to keep track of the count.
const Stores = component$(() => {
const counter = useCounter(1);
// Reactivity happens even for nested objects and arrays
const userData = useStore({
name: 'Manu',
address: {
address: '',
city: ''
},
orgs: []
});
// useStore() can also accept a function to calculate the initial value
const state = useStore(() => {
return {
value: expensiveInitialValue()
}
})
return (
<Host>
<div>Counter: {counter.value}</div>
<Child userData={userData} state={state}/>
</Host>
)
});
function useCounter(step: number) {
// Multiple stores can be created in custom hooks for convenience and composability
const counterStore = useStore({
value: 0
});
useClientEffect$(() => {
// Only runs in the client
const timer = setInterval(() => {
counterStore.value += step;
}, 500);
return () => {
clearInterval(timer);
};
});
return counterStore;
}
useRef()
A very thin wrapper around useStore()
including the proper type signature to be passed to the ref
property in JSX.
export function useRef<T = Element>(current?: T): Ref<T> {
return useStore({ current });
}
Example
const Cmp = component$(() => {
const input = useRef<HTMLInputElement>();
useClientEffect$((track) => {
const el = track(input, 'current')!;
el.focus();
});
return (
<Host>
<input type="text" ref={input}/>
</Host>
)
});
useWatch$()
Reruns the watchFn
when the observed inputs change.
Use useWatch
to observe changes on a set of inputs, and then re-execute the watchFn
when those inputs change.
The watchFn
only executes if the observed inputs change. To observe the inputs use the obs
function to wrap property reads. This creates subscriptions that will trigger the watchFn
to re-run.
Example
The useWatch
function is used to observe the state.count
property. Any changes to the state.count
cause the watchFn
to execute which in turn updates the state.doubleCount
to the double of state.count
.
const Cmp = component$(() => {
const store = useStore({
count: 0,
doubleCount: 0,
debounced: 0
});
// Double count watch
useWatch$((track) => {
const count = track(store, 'count');
store.doubleCount = 2 * count;
});
// Debouncer watch
useWatch$((track) => {
const doubleCount = track(store, 'doubleCount');
const timer = setTimeout(() => {
store.debounced = doubleCount;
}, 2000);
return () => {
clearTimeout(timer);
};
});
return (
<Host>
<div>{store.count} / {store.doubleCount}</div>
<div>{store.debounced}</div>
</Host>
)
});
useClientEffect$()
const Timer = component$(() => {
const store = useStore({
count: 0
});
useClientEffect$(() => {
// Only runs in the client
const timer = setInterval(() => {
store.count++;
}, 500);
return () => {
clearInterval(timer);
};
});
return (
<Host>
{store.count}
</Host>
)
});
useMount$()
Register a hook that executes on component creation. useMount$()
will block the rendering of the component until after useMount$()
callback resolves. (This is useful for fetching asynchronous data and delaying rendering until data is received, ensuring that the rendered component contains the data.).
While useMount$()
executes both on the server and on the client, it runs exactly once. (Either on the server or on the client depending on where the component got first rendered.)
See also: useServerMount$()
that have same semantics but only run on server.
Example
const Cmp = component$(() => {
const store = useStore({
users: []
});
useMount$(async () => {
// This code will run on component creation to fetch the data.
store.users = await db.requestUsers();
});
return (
<Host>
{store.users.map((user => (
<User user={user}/>
)))}
</Host>
)
});
interface User {
name: string;
}
function User(props: {user: User}) {
return (
<div>Name: {props.user.name}</div>
)
}
useServerMount$()
Registers a server mount hook that runs only in the server when the component is first mounted.
Example
const Cmp = component$(() => {
const store = useStore({
users: []
});
useServerMount$(async () => {
// This code will ONLY run once in the server, when the component is mounted
store.users = await db.requestUsers();
});
return (
<Host>
{store.users.map((user => (
<User user={user}/>
)))}
</Host>
)
});
interface User {
name: string;
}
function User(props: {user: User}) {
return (
<div>Name: {props.user.name}</div>
)
}
useHostElement()
Retrieves the Host Element of the current component.
NOTE: useHostElement
method can only be used in the synchronous portion of the callback (before any await
statements.)
const Section = component$(() => {
const hostElement = useHostElement();
console.log(hostElement); // hostElement is a HTMLSectionElement
return (
<Host>
I am a section
</Host>
)
}, {
tagName: 'section'
});
useStyles$()
A lazy-loadable reference to component's styles.
Component styles allow Qwik to lazy load the style information for the component only when needed. (And avoid double loading it in case of SSR hydration.)
import styles from './code-block.css?inline';
export const CmpStyles = component$(() => {
useStyles$(styles);
return <Host>Some text</Host>;
});