Skip to content

Instantly share code, notes, and snippets.

@bglgwyng
Last active August 11, 2022 12:25
Show Gist options
  • Save bglgwyng/1ec9232f9d53051ef67d8fd51d274c4b to your computer and use it in GitHub Desktop.
Save bglgwyng/1ec9232f9d53051ef67d8fd51d274c4b to your computer and use it in GitHub Desktop.
import React, { ForwardedRef, forwardRef, memo, useCallback, useEffect, useMemo } from 'react';
import { Camera, CameraProps, useCameraDevices } from 'react-native-vision-camera';
import { atom, useRecoilValue, useRecoilValueLoadable, useResetRecoilState, useSetRecoilState } from 'recoil';
type CameraProxyProps = Omit<CameraProps, 'isActive'>;
export const cameraRefState = atom<ForwardedRef<Camera>>({
key: 'cameraRef',
default: null,
dangerouslyAllowMutability: true,
});
export const cameraPropsState = atom<CameraProxyProps>({
key: 'cameraProps',
});
// eslint-disable-next-line react/display-name
export const WarmCamera = memo(() => {
const devices = useCameraDevices();
const cameraRef = useRecoilValue(cameraRefState);
const ref = useCallback((x: Camera) => {
if (typeof cameraRef === 'function') {
cameraRef(x);
} else if (cameraRef) {
cameraRef.current = x;
}
}, [cameraRef]);
const { state, contents } = useRecoilValueLoadable(cameraPropsState);
// FIXME: valueMaybe doesn't work for now
const cameraProps = state === 'hasValue' ? contents : undefined;
// FIXME: is .front the best option?
if (cameraProps ?? devices.front) {
if (cameraProps) {
console.info('Camera activated!');
} else {
console.info('Camera deactivated!');
}
return (
<Camera
ref={ref}
{...cameraProps ?? { device: devices.front! }}
isActive={!!cameraProps}
/>
);
} else {
console.info('Camera unmounted!');
return null;
}
});
export const useCameraProxy = () => {
const setCameraRef = useSetRecoilState(cameraRefState);
const resetCameraRef = useResetRecoilState(cameraRefState);
const setCameraProps = useSetRecoilState(cameraPropsState);
const resetCameraProps = useResetRecoilState(cameraPropsState);
return useMemo(() =>
// eslint-disable-next-line react/display-name
memo(forwardRef<Camera, CameraProxyProps>((props, ref) => {
console.info('rerender camera proxy');
useEffect(() => {
// NOTE: ref can be callback
setCameraRef(() => ref);
setCameraProps(props);
}, [ref, props]);
useEffect(() => () => {
resetCameraRef();
resetCameraProps();
}, []);
return null;
})),
[]);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment