Skip to content

Instantly share code, notes, and snippets.

@bglgwyng
Last active July 31, 2022 05:37
Show Gist options
  • Save bglgwyng/7458118a8dad6525049ade721974d7e0 to your computer and use it in GitHub Desktop.
Save bglgwyng/7458118a8dad6525049ade721974d7e0 to your computer and use it in GitHub Desktop.
warm camera example
const App = () => {
return (
<View>
<WarmCamera />
<FooPage />
</View>
);
}
const FooPage = () => {
const CameraProxy = useCameraProxy();
// ...
return (
// Everything is the same as `Camera` except there's no `isActive` props.
<CameraProxy
// FIXME: ref={ref} doesn't work for now
ref={(x) => ref.current = x}
device={device}
photo
/>
)
}
import React, { ForwardedRef, forwardRef, useCallback, useEffect } 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,
});
export const cameraPropsState = atom<CameraProxyProps>({
key: 'cameraProps',
});
export const WarmCamera = () => {
const devices = useCameraDevices();
const cameraRef = useRecoilValue(cameraRefState);
const ref = useCallback((x: Camera) => {
if (typeof cameraRef === 'function') {
cameraRef(x);
} else if (cameraRef) {
// FIXME: this doesn't work
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;
}
};
const useCameraProxy = () => {
const setCameraRef = useSetRecoilState(cameraRefState);
const setCameraProps = useSetRecoilState(cameraPropsState);
const resetCameraProps = useResetRecoilState(cameraPropsState);
// eslint-disable-next-line react/display-name
return forwardRef<Camera, CameraProxyProps>((props, ref) => {
useEffect(() => {
setCameraRef(() => ref);
setCameraProps(props);
}, [ref, props]);
useEffect(() => resetCameraProps, []);
return null;
});
};
export default useCameraProxy;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment