useSetup

import { useSetup } from '@xoid/react'

This export can be used for creating local state inside a React component. It creates a value exactly once. Its basic usage is similar to a React.useMemo call.

import { create } from 'xoid'
import { useSetup } from '@xoid/react'
// inside React
const $num = useSetup(() => create(5))

useSetup is actually more suitable than React.useMemo to create values exactly once. According to React docs, "You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components.". useSetup hook is based on useRef, thus it's guaranteed to run the callback exactly once.

When a second argument is provided, it'll be available in the callback argument as a reactive atom.

import { subscribe, use } from 'xoid'
import { useSetup } from '@xoid/react'
const App = (props: Props) => {
useSetup(($props) => {// `$props` has the type: Atom<Props>
$props.focus(s => s.something).subscribe(console.log)
}, props)
...
}

React adapter (Advanced)

Second callback argument is the React adapter. Most xoid users would not need to use this. When the second argument is not destructured, this has no runtime overhead. Its type is exported from the @xoid/react as the following.

type ReactAdapter = {
read: <T>(context: React.Context<T>) => T
effect: (fn: React.EffectCallback) => void
}

.effect

.effect method simply connect to a useEffect call internally.

import { useSetup } from '@xoid/react'
const App = (props: Props) => {
useSetup((_, { effect }) => {
const callback = () => { ... }
effect(() => {
window.addEventListener('resize', callback)
window.addEventListener('orientationchange', callback)
return () => {
window.removeEventListener('resize', callback)
window.removeEventListener('orientationchange', callback)
}
})
})
...
}

You can call as many of them as you want. You can even call them conditionally. They'll connect to the same useEffect call.

import { useSetup } from '@xoid/react'
const App = (props: Props) => {
useSetup((_, { effect }) => {
const callback = () => { ... }
effect(() => {
window.addEventListener('resize', callback)
return () => window.removeEventListener('resize', callback)
})
effect(() => {
window.addEventListener('orientationchange', callback)
return () => window.removeEventListener('orientationchange', callback)
})
})
...
}

.read

.read can be used to read the context conditionally. There's an important note about the .read method. It's the only experimental feature of @xoid/react and relies on React internals. This part of React MIGHT change in the future. You can consider the .read method unsafe and not use it if your React version is -somehow- not fixed. When it's not used, it has no runtime effect. You can see the implementation here. The good thing is, it's known that react-relay uses the same internal, and it's even supported by preact/compat.

import { useSetup } from '@xoid/react'
import { ThemeContext } from './some-module'
const App = (props: Props) => {
useSetup((_, adapter) => {
const theme = adapter.read(ThemeContext)
// do something with the theme
})
...
}
Last updated on