I am new to vue native and im trying to create a page on the app where i can use the camera and capture & show a photo using the expo-camera directive.
This is what i have done:
<template>
<view class="view-container">
<view class="container">
<text>Camera screen</text>
<camera class="container" :type="this.type" />
<touchable-opacity
class="camera-touchable-opacity"
:on-press="capturePic"
>
</view>
<view class="home-btn">
<button title="Go to home screen" #press="goToHomeScreen"></button>
</view>
</view>
</template>
<script>
import * as Permissions from 'expo-permissions';
import { Camera } from 'expo-camera';
export default {
props: {
navigation: { type: Object }
},
data: function() {
return {
hasCameraPermission: false,
type: Camera.Constants.Type.back,
};
},
mounted: function() {
Permissions.askAsync(Permissions.CAMERA)
.then(status => {
hasCameraPermission = status.status == "granted" ? true : false;
}).catch((err)=>{
console.log(err);
});
},
components: { Camera },
methods: {
goToHomeScreen() {
this.navigation.navigate("Home");
},
capturePic: async function() {
if(!camera) return
const photo = await camera.takePictureAsync();
}
}
}
</script>
i receive this warning:
[Unhandled promise rejection: ReferenceError: Can't find variable: camera]
I don't know what i need since i didn't find anything regarding capturing a photo in the docs.
You can refer your camera as this.$refs.camera in your method, since you need to have a reference on the element as ref="camera" in your code..
<camera class="container" :type="this.type" ref="camera"/>
The capture function will be this.$refs.camera.takePictureAsync()
In your code
capturePic: async function() {
if(!camera) return
const photo = await camera.takePictureAsync();
}
Related
We decided to implement a simple onboarding tour on our application, everything was going well on local but once we deploy it to production its crashing showing the next error on devtools:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading '0')
it's kind of hard to debug this and see what is the problem because it's caused on production and its like debugging with the eyes closed.
the bug/error that the console show it's and undefined and by logic will crash too on local, but this it's not the case
The error is caused after we pass the first step like you can see on this video(also you can se how it's working locally:
VIDEO WITH THE ISSUE
They way the joyride its implemented consists on two big keys
the first one its the joyride wrapper:
import { useEffect, useState } from 'react';
import Joyride, { CallBackProps, STATUS, Step } from 'react-joyride';
import { Tooltip } from './components/tool-tip';
import { OnboardingTourJoyrideProps, ValidSteps } from '../../types/onboarding-tour';
import { useGuidedTour } from '../../hooks/use-guided-tour';
export function OnboardingTourJoyride({ start, stepToCheck }: OnboardingTourJoyrideProps): JSX.Element {
const { dashBoardSteps, terminalAppSteps, cloudAppSteps } = useGuidedTour();
const [steps, setSteps] = useState<Step[]>(dashBoardSteps);
const [run, setRun] = useState<boolean>(false);
const [resetTour, setResetTour] = useState<boolean>(false);
const [stepToInitRestart, setStepToInitRestart] = useState<number>(0);
function handleSteps() {
switch (stepToCheck) {
case ValidSteps.DASHBOARD_STEPS:
setSteps(dashBoardSteps);
setStepToInitRestart(dashBoardSteps.length - 1);
break;
case ValidSteps.TERMINAL_APP_STEPS:
setSteps(terminalAppSteps);
setStepToInitRestart(terminalAppSteps.length - 1);
break;
case ValidSteps.CLOUD_APP_STEPS:
setSteps(cloudAppSteps);
setStepToInitRestart(cloudAppSteps.length - 1);
}
}
useEffect(() => {
const onboardinIsCompletedOrSkipped = handleCheckIfTourIsComplete();
if (!onboardinIsCompletedOrSkipped) {
handleSteps();
if (start) setRun(true);
}
}, [start]);
useEffect(() => {
if (resetTour) {
setRun(true);
setResetTour(false);
}
}, [resetTour]);
function handlePropertyToSaveOnLocalStorage() {
switch (stepToCheck) {
case ValidSteps.DASHBOARD_STEPS:
localStorage.setItem('ONBOARDING_TOUR_DASHBOARD', 'true');
break;
case ValidSteps.TERMINAL_APP_STEPS:
localStorage.setItem('ONBOARDING_TOUR_TERMINAL_APP', 'true');
break;
case ValidSteps.CLOUD_APP_STEPS:
localStorage.setItem('ONBOARDING_TOUR_CLOUD_APP', 'true');
break;
}
}
function handleCheckIfTourIsComplete() {
if (stepToCheck === ValidSteps.DASHBOARD_STEPS) {
return localStorage.getItem('ONBOARDING_TOUR_DASHBOARD');
} else if (stepToCheck === ValidSteps.TERMINAL_APP_STEPS) {
return localStorage.getItem('ONBOARDING_TOUR_TERMINAL_APP');
} else if (stepToCheck === ValidSteps.CLOUD_APP_STEPS) {
return localStorage.getItem('ONBOARDING_TOUR_CLOUD_APP');
}
}
function handleJoyrideCallback(data: CallBackProps) {
const { status, action, index } = data;
console.log(data);
const finishedStatuses: string[] = [STATUS.FINISHED, STATUS.SKIPPED];
if (index === stepToInitRestart && status === STATUS.SKIPPED) {
setRun(false);
setResetTour(true);
}
if (finishedStatuses.includes(status)) {
if (action === 'skip') {
setRun(false);
handlePropertyToSaveOnLocalStorage();
}
setRun(false);
handlePropertyToSaveOnLocalStorage();
}
}
return (
<Joyride
tooltipComponent={Tooltip}
disableScrolling={true}
callback={handleJoyrideCallback}
continuous
hideCloseButton
run={run}
scrollToFirstStep
showProgress={false}
showSkipButton={true}
steps={steps}
styles={{
options: {
zIndex: 10000,
},
}}
/>
);
}
which its a simple wrapper that contains all the logic to rehuse the same component across the app
and the other one it's the custom tooltip component:
import { Box, CloseButton, Flex, Text } from '#chakra-ui/react';
import { TooltipRenderProps } from 'react-joyride';
import { Button } from '../../button';
import { useIntl } from 'react-intl';
export function Tooltip({
backProps,
continuous,
index,
isLastStep,
primaryProps,
skipProps,
step,
tooltipProps,
size,
}: TooltipRenderProps): JSX.Element {
const intl = useIntl();
const steps = {
currentStep: index,
stepsLength: size - 2,
};
function handleResetOrBackStep(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
if (isLastStep) {
skipProps.onClick(e);
} else {
backProps.onClick(e);
}
}
function handleCloseButton(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
if (isLastStep) {
primaryProps.onClick(e);
} else {
skipProps.onClick(e);
}
}
function handleFowardButton() {
return continuous
? index !== 0 && !isLastStep
? intl.formatMessage({ id: 'buttons.next' })
: isLastStep
? intl.formatMessage({ id: 'buttons.finish' })
: intl.formatMessage({ id: 'buttons.startTour' })
: null;
}
function handleShowStepsCounter() {
return index !== 0 && !isLastStep ? (
<Text fontSize="16px">
{intl.formatMessage(
{ id: 'onboardingTour.toolTip.stepsCounter' },
{
currentStep: steps.currentStep,
totalSteps: steps.stepsLength,
},
)}
</Text>
) : (
!isLastStep && (
<Button variant="outline" {...skipProps}>
{intl.formatMessage({ id: 'buttons.skipTour' })}
</Button>
)
);
}
function handleBackwardButton() {
return isLastStep
? intl.formatMessage({ id: 'buttons.restartTour' })
: intl.formatMessage({ id: 'buttons.previous' });
}
return (
<Box {...tooltipProps} background="white" p="48px" w="100%" borderRadius="6px">
<Box padding="md">
<Flex justifyContent="space-between" align="baseline" marginBottom="15px">
{step.title && (
<Text fontSize="20px" fontWeight="700">
{step.title}
</Text>
)}
<CloseButton onClick={e => handleCloseButton(e)} />
</Flex>
{step.content && (
<Box>
<Text w="504px" fontSize="16px" fontWeight="400" lineHeight="26px" marginBottom="48px">
{step.content}
</Text>
</Box>
)}
</Box>
<Box>
<Flex justifyContent="space-between" align="center">
{handleShowStepsCounter()}
<Flex w={isLastStep ? '100%' : ''} justifyContent="space-between">
{index !== 0 && (
<Button marginRight="12px" variant="outline" onClick={e => handleResetOrBackStep(e)}>
{handleBackwardButton()}
</Button>
)}
<Button h="35px" {...primaryProps}>
{handleFowardButton()}
</Button>
</Flex>
</Flex>
</Box>
</Box>
);
}
I don't know if anyone have experience with a similar issue, I google it and search all across SO and the issues on the library repository.
Also it's weird because on the pass I worked with react-joyride and deployed to production and there is no any problem.
To put you all in context, we are using next with a framework called Gasket.
Had the same issue.
The problem is with the experimental SWC minification using the swcMinify config. It tries to optimize too much, leading to the offset variable not being used before it is declared.
It's not a problem with the version of popper.js or any other dependency. To fix the problem you just need to set swcMinify: false in your next config (also updating nextjs to 13.1.1 fixes the problem in my case).
Here is discussion about: https://github.com/gilbarbara/react-joyride/issues/857
I am trying to build a React.js SharePoint modern web part, which have the following capabilities:-
Inside the Web Part settings page >> there are 2 fields named as "Who We Are" & "Our Value" which allow the user to enter HTML.
The web part will render 2 buttons "Who We Are" & "Our Value" >> and when the user clicks on any button >> a Popup will be shown with the entered HTML code in step-1
Something as follow:-
But to be able to render HTML code as Rich-Text inside my Web Part, i have to use the dangerouslySetInnerHTML attribute inside the .tsx file. as follow:-
import * as React from 'react';
import { useId, useBoolean } from '#fluentui/react-hooks';
import {
getTheme,
mergeStyleSets,
FontWeights,
Modal,
IIconProps,
IStackProps,
} from '#fluentui/react';
import { IconButton, IButtonStyles } from '#fluentui/react/lib/Button';
export const MYModal2 = (myprops) => {
const [isModalOpen, { setTrue: showModal, setFalse: hideModal }] = useBoolean(false);
const [isPopup, setisPopup] = React.useState(true);
const titleId = useId('title');
React.useEffect(() => {
showModal();
}, [isPopup]);
function ExitHandler() {
hideModal();
setisPopup(current => !current)
myprops.handler();
}
return (
<div>
<Modal
titleAriaId={titleId}
isOpen={isModalOpen}
onDismiss={ExitHandler}
isBlocking={true}
containerClassName={contentStyles.container}
>
<div className={contentStyles.header}>
<span id={titleId}>Modal Popup</span>
<IconButton
styles={iconButtonStyles}
iconProps={cancelIcon}
ariaLabel="Close popup modal"
onClick={ExitHandler}
/>
</div>
<div className={contentStyles.body}>
<p dangerouslySetInnerHTML={{__html:myprops.OurValue}}>
</p>
</div>
</Modal>
</div>
);
};
const cancelIcon: IIconProps = { iconName: 'Cancel' };
const theme = getTheme();
const contentStyles = mergeStyleSets({
container: {
display: 'flex',
flexFlow: 'column nowrap',
alignItems: 'stretch',
},
header: [
// eslint-disable-next-line deprecation/deprecation
theme.fonts.xLarge,
{
flex: '1 1 auto',
borderTop: '4px solid ${theme.palette.themePrimary}',
color: theme.palette.neutralPrimary,
display: 'flex',
alignItems: 'center',
fontWeight: FontWeights.semibold,
padding: '12px 12px 14px 24px',
},
],
body: {
flex: '4 4 auto',
padding: '0 24px 24px 24px',
overflowY: 'hidden',
selectors: {
p: { margin: '14px 0' },
'p:first-child': { marginTop: 0 },
'p:last-child': { marginBottom: 0 },
},
},
});
const stackProps: Partial<IStackProps> = {
horizontal: true,
tokens: { childrenGap: 40 },
styles: { root: { marginBottom: 20 } },
};
const iconButtonStyles: Partial<IButtonStyles> = {
root: {
color: theme.palette.neutralPrimary,
marginLeft: 'auto',
marginTop: '4px',
marginRight: '2px',
},
rootHovered: {
color: theme.palette.neutralDark,
},
};
And to secure the dangerouslySetInnerHTML, i did the following steps:-
1- Inside my Node.Js CMD >> i run this command inside my project directory:-
npm install dompurify eslint-plugin-risxss
2- Then inside my above .tsx i made the following modifications:-
I added this import import { sanitize } from 'dompurify';
An I replaced this unsafe code <p dangerouslySetInnerHTML={{__html:myprops.OurValue}}></p> with this <div dangerouslySetInnerHTML={{ __html: sanitize(myprops.OurValue) }} />
So I have the following question:-
Now my approach (of using sanitize(myprops.OurValue) will/should securely render HTML as Rich-Text inside the popup since i am using the sanitize function which is part of the dompurify eslint-plugin-risxss. but i read another approach which mentioned that to securely render HTML as Rich-Text inside the popup, we can use the html-react-parser package as follow {parse(myprops.OurValue)}. So what are the differences between using 'html-react-parser' & using 'dompurify eslint-plugin-risxss' to securely render an HTML code as Rich-Text inside the React web part's popup?
Here is my Full web part code:-
inside the MyModalPopupWebPart.ts:-
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '#microsoft/sp-core-library';
import {
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '#microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '#microsoft/sp-webpart-base';
import * as strings from 'MyModalPopupWebPartStrings';
import MyModalPopup from './components/MyModalPopup';
import { IMyModalPopupProps } from './components/IMyModalPopupProps';
export interface IMyModalPopupWebPartProps {
description: string;
WhoWeAre: string;
OurValue:string;
}
export default class MyModalPopupWebPart extends BaseClientSideWebPart<IMyModalPopupWebPartProps> {
public render(): void {
const element: React.ReactElement<IMyModalPopupProps> = React.createElement(
MyModalPopup,
{
description: this.properties.description,
WhoWeAre: this.properties.WhoWeAre,
OurValue: this.properties.OurValue
}
);
ReactDom.render(element, this.domElement);
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('WhoWeAre', {
label: "who We Are",
multiline: true
}),
PropertyPaneTextField('OurValue', {
label: "Our value"
}), PropertyPaneTextField('description', {
label: "Description",
multiline: true
}),
]
}
]
}
]
};
}
}
inside the MyModalPopup.tsx:-
import * as React from 'react';
import { IMyModalPopupProps } from './IMyModalPopupProps';
import { DefaultButton } from '#fluentui/react/lib/Button';
import { MYModal } from './MYModal';
import { MYModal2 } from './MYModal2';
interface IPopupState {
showModal: string;
}
export default class MyModalPopup extends React.Component<IMyModalPopupProps, IPopupState> {
constructor(props: IMyModalPopupProps, state: IPopupState) {
super(props);
this.state = {
showModal: ''
};
this.handler = this.handler.bind(this);
this.Buttonclick = this.Buttonclick.bind(this);
}
handler() {
this.setState({
showModal: ''
})
}
private Buttonclick(e, whichModal) {
e.preventDefault();
this.setState({ showModal: whichModal });
}
public render(): React.ReactElement<IMyModalPopupProps> {
const { showModal } = this.state;
return (
<div>
<DefaultButton onClick={(e) => this.Buttonclick(e, 'our-value')} text="Our Value" />
{ showModal === 'our-value' && <MYModal2 OurValue={this.props.OurValue} myprops={this.state} handler={this.handler} />}
<DefaultButton onClick={(e) => this.Buttonclick(e, 'who-we-are')} text="Who We Are" />
{ showModal === 'who-we-are' && <MYModal WhoWeAre={this.props.WhoWeAre} myprops={this.state} handler={this.handler} />}
</div>
);
}
}
Actually, html-react-parser returns ReactJs object, and its return type is like React.createElement or like type of called JSX.
Using DOMPurify.sanitize will return safe pure HTML elements which those are different to the object that html-react-parser returns. the risxss ESLint plugin will force you to use sanitizing with any kind of sanitize function or library, that I left an answer to your other question to how to Sanitize your string HTML.
Eventually, using sanitizing is better because is the html-react-parser will convert your string HTML to ReactJs object with some tiny changes that would be dangerous because it is possible to have some script of string HTML in the project and it maybe will be harmful it just remove the onclick or onload, etc, from HTML tags but sanitizing will remove all possible harmful tags. also sanitizing will receive configuration, which means you can have your own options for sanitizing.
So I'm trying to reproduce a simple example code of react-qr-scanner, but in the code below as I try to embed result in the p tag I get an error, saying objects cannot be embedded inside that. What am I doing wrong?
import React, { Component } from 'react';
import QrReader from 'react-qr-scanner';
class Scan extends Component {
constructor(props) {
super(props);
this.state = {
result : 'Hold QR Code steady and clear to scan',
}
this.previewStyle = {
height : 700,
width : 1000,
display : 'flex',
justifyContent : "center",
}
this.camStyle = {
display : 'flex',
justifyContent : 'center',
marginTop : '-50px',
}
this.textStyle= {
fontSize : '30px',
"text-align" : 'center',
marginTop : '-50px',
}
this.handleScan = this.handleScan.bind(this);
}
handleScan(data) {
this.setState({
result : data,
});
}
handleError(err) {
console.log(err);
}
render() {
return (
<>
<div className="stream-container" >
<QrReader
delay={100}
onError={this.handleError}
onScan={this.handleScan}
/>
</div>
<p style={this.resultStyle}>
{this.state.result} //here error occurs saying I cannot embed it inside here
</p>
</>
);
}
}
export default Scan;
The docs of react-qr-scanner has this exact example, so why isn't it working on mine? Please help.
In the function of handleScan, data is an object, 'Objects are not valid as a React child'.
Try to make your fuctions with arrow -
handleScan = (data) => {
this.setState({
result: data,
});
}
handleError = (err) => {
console.log(err);
}
I'm building a react application, and on my HomePage, I have the component 'CategoriesList'.
When I'm on the HomePage, the 'Categories List' works well, but when I navigated to ProductDetails page with react-router-dom, I found this error:
"NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node."
'CategoriesList' uses Flickty. I tried to remove Flickity, and... Works well. But I need to use Flickity.
Can anyone help me?
CategoryList Component:
const CategoryList = ({list, popupOpen, refreshProductList}) => {
return (
<Container>
<Slider
options={{
cellAlign: 'center',
draggable: true,
groupCells: true,
contain: false,
pageDots: false,
}}
style={ popupOpen ? ({opacity: 0.05}) : null}
>
{list.map((category, index) => (
<Category key={index}>{category}</Category>
))}
</Slider>
</Container>
);
}
Flickty Slider Component:
import Flickity from 'flickity';
import 'flickity/dist/flickity.min.css';
export default class Slider extends Component {
constructor(props) {
super(props);
this.state = {
flickityReady: false,
};
this.refreshFlickity = this.refreshFlickity.bind(this);
}
componentDidMount() {
this.flickity = new Flickity(this.flickityNode, this.props.options || {});
this.setState({
flickityReady: true,
});
}
refreshFlickity() {
this.flickity.reloadCells();
this.flickity.resize();
this.flickity.updateDraggable();
}
componentWillUnmount() {
this.flickity.destroy();
}
componentDidUpdate(prevProps, prevState) {
const flickityDidBecomeActive = !prevState.flickityReady && this.state.flickityReady;
const childrenDidChange = prevProps.children.length !== this.props.children.length;
if (flickityDidBecomeActive || childrenDidChange) {
this.refreshFlickity();
}
}
renderPortal() {
if (!this.flickityNode) {
return null;
}
const mountNode = this.flickityNode.querySelector('.flickity-slider');
if (mountNode) {
return ReactDOM.createPortal(this.props.children, mountNode);
}
}
render() {
return [
<div style={this.props.style} className={'test'} key="flickityBase" ref={node => (this.flickityNode = node)} />,
this.renderPortal(),
].filter(Boolean);
}
}
If you want to use Flickity along with React instead of creating your own component, I highly recommend using react-flickity-component. It's also easy to use:
Tip: if you use wrapAround option in Flickity set
disableImagesLoaded prop ture (default is false).
import Flickity from 'react-flickity-component'
const flickityOptions = {
autoPlay: 4000,
wrapAround: true
}
function Carousel() {
return (
<Flickity
disableImagesLoaded
options={flickityOptions} // Takes flickity options {}
>
<img src="/images/placeholder.png"/>
<img src="/images/placeholder.png"/>
<img src="/images/placeholder.png"/>
</Flickity>
)
}
I'm follow the steps of this dependencie:
http://jossmac.github.io/react-images/
And it isn't work. No picture showing and there is showing an error message:
index.js:2178 Warning: Failed prop type: The prop onClose is marked
as required in Lightbox, but its value is undefined
Here is my code:
import React, { Component } from "react";
import Lightbox from "react-images";
const URL_INTERIORES = "http://localhost:3001/interiores";
const LIGHTBOX_IMAGE_SET = [
{
src: "/images/int_02.jpg",
caption: "A forest",
// As an array
srcSet: ["/images/int_02.jpg", "/images/int_02.jpg"]
},
{
src: "/images/int_02.jpg",
// As a string
srcSet: "/images/int_02.jpg 1024w, /images/int_02.jpg 800w, /images/int_02.jpg 500w, /images/int_02.jpg 320w"
}
];
class Interiores extends Component {
render() {
const { open } = this.state;
return (
<div>
<div>
<Lightbox
images={LIGHTBOX_IMAGE_SET}
isOpen={this.state.lightboxIsOpen}
onClickPrev={this.gotoPrevLightboxImage}
onClickNext={this.gotoNextLightboxImage}
onClose={this.closeLightbox}
/>
</div>
</div>
);
}
}
export default Interiores;
Does anybody know how to solve it? Tahnk you
Consider adding all the missing handlers & state in your class:
class Interiores extends Component {
state = {
lightboxIsOpen: false
}
gotoPrevLightboxImage() {
// Add the logic here
}
gotoNextLightboxImage() {
// Add the logic here
}
closeLightbox(e) {
// Add the logic here
}
render() {
const { lightboxIsOpen } = this.state;
return (
<div>
<Lightbox
images={LIGHTBOX_IMAGE_SET}
isOpen={lightboxIsOpen}
onClickPrev={() => this.gotoPrevLightboxImage()}
onClickNext={() => this.gotoNextLightboxImage()}
onClose={e => this.closeLightbox(e)}
/>
</div>
);
}
}