Integration with React
Using a react component inside a Unison component and vice-versa
When you declare a Unison component, it produces a React component that renders standard JSX. You can pass your component as a child as usual.
Using React hook inside a Unison component
In a Unison component, you can't use React hooks as usual. Technically, you can call a React hook, but due to the one-time execution paradigm of a Unison component, the hook won't be called over time and it might introduce some bugs.
To bring a react hook to the unisonjs world, you need to wrap it with: toUnisonHook
import { useQuery as uq } from "@tanstack/react-query";
import { $unison, toUnisonHook } from "@unisonjs/vue";
const useQuery = toUnisonHook(uq);
const TodoList = $unison(() => {
const { data } = useQuery({
queryKey: ["todos"],
queryFn: getTodos,
});
return () => (
<ul>
{data.value.map((item) => (
<li>{item.text}</li>
))}
</ul>
);
});
export default TodoList;
By default, toUnisonHook
will track individually every first depth properties of an object. Also it tracks only non-object values to prevent excessive rerender.
If you need to track the result as a whole, you can pass { shallow: true }
as an option to toUnisonHook
import { useQueryClient as uqc } from "@tanstack/react-query";
import { toUnisonHook, $unison } from "@unisonjs/vue";
const useQueryClient = toUnisonHook(uqc, { shallow: true });
const PrintQueryClient = $unison(() => {
const client = useQueryClient();
return () => <p>{JSON.stringify(client.value)}</p>;
});
export default PrintQueryClient;
Using Unison (Vue) primitives inside a React component
You can consume Unison (Vue) primitives like ref
or reactive
inside standard React components by using the useUnison
hook. This enables React components to integrate seamlessly with unisonjs state.
Example with ref
import { ref, useUnison } from "@unisonjs/vue";
const count = ref(0);
function Counter() {
useUnison();
return <button onClick={() => count.value++}>count is {count.value}</button>;
}
Example with reactive
import { reactive, useUnison } from "@unisonjs/vue";
const store = reactive({ count: 0 });
function Counter() {
useUnison();
return (
<button onClick={() => store.count++}>
count is {store.count}
</button>
);
}
Example with a Custom Hook
// hooks/counter.js
import { ref } from "@unisonjs/vue";
const count = ref(0);
export function useCounter() {
return {
value: count.value,
increment: () => count.value++,
decrement: () => count.value--,
};
}
// components/Counter.jsx
import { useUnison } from "@unisonjs/vue";
import { useCounter } from "../hooks/counter";
function Counter() {
useUnison();
const { value, increment, decrement } = useCounter();
return (
<div>
<button onClick={increment}>+</button>
<span>{value}</span>
<button onClick={decrement}>-</button>
</div>
);
}
Using composable inside a react component
If you have created some composables that you want to use in a normal React component, you can wrap your composables with the createReactHook
helper :
import { createReactHook } from "@unisonjs/vue";
export const useOnlineStatus = createReactHook(() => {
const isOnline = ref(true);
function handleOnline() {
isOnline.value = true;
}
function handleOffline() {
isOnline.value = false;
}
watchPostEffect((onCleanup) => {
window.addEventListener("online", handleOnline);
window.addEventListener("offline", handleOffline);
onCleanup(() => {
window.removeEventListener("online", handleOnline);
window.removeEventListener("offline", handleOffline);
});
});
return isOnline;
});
Don't forget to call the useUnison()
hook
// components/online-status.jsx
import { useUnison } from "@unisonjs/vue";
function OnlineStatus() {
useUnison();
const isOnline = useOnlineStatus();
return <p>Connected: {isOnline.value}</p>;
}