React Integration (useGetter)

React Integration

Taking into account the available ZDK API, we can conveniently get the current value and listen for its changes. How to use it in react?

For example, let’s create a view in react that will show the current status of the webSocket connection.

file.tsx
const MyComponentWithStatus: FC = () => {
  // create state with initial value equal to current value of the webSocket status
  const [status, setStatus] = useState(() => webSocketModule.data.status.val());
 
  // create useEffect that will be triggered once after
  // creating the component (deps must be empty!)
  useEffect(() => {
    // listen to changes of the status value and use setStatus function
    // to update the value when it changes (it will rerender the component with new value).
    const unlisten = webSocketModule.data.status.onChange((status) => {
      setStatus(status)
    })
    // remember to call unlisten function returned by onChange
    // function to stop listening when the component disappear
    return () => {
     unlisten()
    }
  }, []);
 
  return <div>{status}</div>
}

The code will work, but all this logic can be encapsulated in a custom hook so you don’t have to repeat yourself every time you want to use a value from the ZDK inside a react component.

file.tsx
type ExtractType<T> = T extends IGetter<infer VALUE> ? VALUE : never;
 
export function useGetter<T extends IGetter<any>>(getter: T): ExtractType<T>;
export function useGetter<T extends IGetter<any>>(getter?: T | undefined): ExtractType<T> | undefined;
export function useGetter<T extends IGetter<any>>(getter?: T): ExtractType<T> | undefined {
  const unlisten = useRef<() => void>();
  const [state, setState] = useState<ExtractType<T> | undefined>(getter?.val);
 
  useEffect(() => {
   if (!getter) return;
   unlisten.current = getter.onAutoChange((v) => {
     setState(v);
   });
   return () => {
     unlisten.current?.();
   };
  }, [getter]);
 
  return state;
};

The approach with the hook looks clearer in the components compared to the previous example, (we recommend to use the useGetter hook):

file.tsx
const MyComponentWithStatus: FC = () => {
  const status = useGetter(webSocketModule.data.status);
  return <div>{status}</div>
}
⚠️

The useGetter hook will be added to ZDK react utils in future.