--- tags: zeta-dom-react --- # Utilities ## `classNames` Concatenates a list of CSS class names. ## `createBreakpointContext` ==Since `v0.2.3`== Creates a state object and corresponding hook for multiple media queries. ```typescript const { breakpoints, useBreakpoint } = createBreakpointContext({ isMobile: '(max-width: 700px)', isTablet: '(max-width: 900px)' }); function Component(props) { const { isMobile, isTablet } = useBreakpoint(); /* ... */ } // breakpoints is a state object that gives // whether each media query matches now // e.g. next line may give { isMobile: true, isTablet: false } console.log(breakpoints); ``` ## `domEventRef` Allows binding listeners to Zeta DOM events. ```typescript! function Component(props) { const [state, setState] = useState(0); return ( <div ref={domEventRef({ focusin })}></div> ); function focusin() { // callback has access to latest props or state console.log(props.value, state); } } ``` ## `innerTextOrHTML` ==Since `v0.3.1`== Either inserts content using either `children`, or `dangerouslySetInnerHTML` if input is an object with `__html` property. ```typescript function Component(props) { return <div {...innerTextOrHTML(props.content)}></div>; } ``` ## `partial` Partially updates a composite object state. It can clean up code if the partial update does not depends on previous state. ```typescript function Component(props) { const [state, setState] = useState({ foo: 0, bar: 0 }); function onClick() { partial(setState)({ foo: 1 }); // equivalent to: // setState(s => ({ ...s, foo: 1 })); } } ``` It is also cleaner when passing event callback to child components: ```typescript function Component(props) { const [state, setState] = useState({ foo: 0, bar: 0 }); return <Other onChange={partial(setState, 'bar')}></Other> // equivalent to: // <Other onChange={bar => setState(s => ({ ...s, bar }))}></Other> } ``` ## `useAsync` See [useAsync](/Rk3_Cez4RFyniUeMMN0eSA). ## `useDispose` Creates a cleanup callback collector. Callbacks pushed into the queue will be called when the component is unmounted. ```typescript function Component(props) { const dispose = useDispose(); useEffect(() => { doSomeWork().then(() => { dispose.push(() => console.log('Component unmounted')); }); }, []]); /* ... */ } ``` Callbacks can also be called manually by calling the `DisposeCallback`. Executed callbacks are removed from the queue so that they will not be called twice. ```typescript function Component(props) { const dispose = useDispose(); useEffect(() => { setTimeout(() => { dispose(); // cleanup manually }, 1000); }, []); /* ... */ } ``` ## `useMediaQuery` ==Since `v0.2.3`== Triggers component update when the matching state of the given media query has changed. ```typescript function Component(props) { const isMobile = useMediaQuery('(max-width: 700px)'); /* ... */ } ``` ## `useMemoizedFunction` Creates a memoized callback that invokes the supplied callback when called. This reduces unnecessary `useEffect` cycles but at the same time the correct callback supplied in the last component cycle, which associates to the latest component state, can be called. ```typescript function Component(props) { const cb = useMemoizedFunction(() => { console.log(props.value); }); useEffect(() => { // prints latest props.value every 1s setInterval(cb, 1000); }, [cb]); } ``` ## `useObservableProperty` Listens and gets the value of a property of an object. The component is refreshed when the property has been updated. ```typescript const obj = { value: 1 }; function Component() { const value = useObservableProperty(obj, 'value'); return (<div>Value is {value}</div>); } // Component will print "Value is 2" when somewhere call update function update() { obj.value = 2; } ``` ## `useRefInitCallback` Creates a React ref callback, that will invoke the supplied callback only once for each a new DOM element created. It is generally used for one-time setup for DOM element, for example binding Zeta DOM events: ```typescript function Component(props) { const initRef = useRefInitCallback((element: HTMLElement) => { // this callback will execute exactly once for the <DIV> element zeta.dom.on(element, 'focusreturn', (e) => { /* ... */ }); }); return (<div ref={initRef}></div>); } ``` :::warning **Important**: Since the callback is only called once for a DOM element in the component's lifetime, any variables referenced in the callback must be unchanged throughout the lifetime, such as created from [`React.useRef`](https://reactjs.org/docs/hooks-reference.html#useref). For functions, it can be wrapped by [`useMemoizedFunction`](#useMemoizedFunction). ::: ```typescript function Component(props) { const [counter, setCounter] = useState(0); const [singletionObject] = useState({ count: 0 }); const counterRef = useRef(0); const memoizedCallback = useMemoizedFunction(props.callback); const inlineCallback = () => { /* ... */ }; const memoizedInlineCallback = useMemoizedFunction(inlineCallback); const initRef = useRefInitCallback((element: HTMLElement) => { // OK singletionObject.count++; counterRef.current++; // OK, see `useMemoizedFunction` memoizedCallback(); memoizedInlineCallback(); // not OK counter; // -> state might change over the lifetime props.callback(); // -> anything on props might be changed over the lifetime // also callback may be bound to previous states // which results in memory leaks inlineCallback(); // -> definitely memory leaks }); return (<div ref={initRef}></div>); } ``` ## `useUpdateTrigger` ==Since `v0.3.4`== Creates a callback that trigger component update. ## `withSuspense` ==Since `v0.3.1`== Creates a lazy component wrapped with `<Suspense>`.