Laser Barcode Scanner Issue in React (Expo) - reactjs

Is it possible using laser barcode scanner in expo?
i did something like this , but i cant make it to work.
Basicly im trying to get the scanned data from PDA(android) device , that when i click to scan on PDA i get info to a console log per example to test it ,later on i will need that data to spread to a specific number of inputboxes.
Right now when i clicked on the scan button nothing happens but if i try to use a phone with a camera it works without the click function.
import { Text, View, StyleSheet, Button } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
export default function App() {
const [scanned, setScanned] = useState(false);
const handleBarCodeScanned = ({ data }) => {
setScanned(true);
alert(`${data}`);
};
const handleKeyPress = (event) => {
if(event.key === 'Enter'){
handleBarCodeScanned
}
};
return (
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleKeyPress}
></BarCodeScanner>
);
}```

Related

How to add searchinputs as array in localStorage with React TypeScript

I'm trying to make a search bar, where the search will occur once the button (or enter) is clicked. To this, I want to save the searched phrases in localStorage.
I have no problem with the first part. Things work fine when searching with a button or on enter-click. However, when I try to add the search as an array to localStorage I keep getting issues (like string doesn't work with an array, and many more. I've tried A LOT of different things). I've done this with JS and vanilla React, but never with TS.
In the provided code, the search works, and to put in at least something (as simple as I could) - the latest value is also stored in localStorage.
The code can be found here
Or here:
// index file
import { useState } from "react";
import { Searchbar } from "./searchbar";
import { SearchContainer } from "./style";
export const Search = () => {
const [search, setSearch] = useState<string>("");
return (
<SearchContainer>
<Searchbar setSearch={setSearch} />
<p>SEARCHED: {search}</p>
</SearchContainer>
);
};
// search bar file
import { useRef, KeyboardEvent, useEffect } from "react";
type SearchProps = {
setSearch: React.Dispatch<React.SetStateAction<string>>;
};
export const Searchbar = ({ setSearch }: SearchProps) => {
// with useRef we don't have to reload the page for every input
const inputRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
setSearch(String(inputRef.current?.value));
localStorage.setItem("form", JSON.stringify(inputRef.current?.value)); // Issue here
};
// Enable search with the enter-key
const log = (e: KeyboardEvent): void => {
e.key === "Enter" ? handleClick() : null;
};
useEffect(() => {
const value = localStorage.getItem("form");
value ? JSON.parse(value) : "";
}, [setSearch]);
return (
<div>
<input
type="text"
autoComplete="off"
ref={inputRef}
placeholder="search game..."
onKeyDown={log}
/>
<button onClick={handleClick}>SEARCH</button>
</div>
);
};
I've been on this for a while now so any help is appreciated. (I am also trying to learn TS from scratch, but until I get to here...).

Using Experimental Chrome API in React?

I am trying to use Chrome nfc api (WEB NFC) inside of react, so when you open the react page on mobile with nfc enabled and press a button it check to see if nfc scan.
I was reading through the doc and the sample code to do this is,
scanButton.addEventListener("click", async () => {
log("User clicked scan button");
try {
const ndef = new NDEFReader();
await ndef.scan();
log("> Scan started");
ndef.addEventListener("readingerror", () => {
log("Argh! Cannot read data from the NFC tag. Try another one?");
});
ndef.addEventListener("reading", ({ message, serialNumber }) => {
log(`> Serial Number: ${serialNumber}`);
log(`> Records: (${message.records.length})`);
});
} catch (error) {
log("Argh! " + error);
}
});
My react page is currently,
import { Button } from "#material-ui/core";
import React from "react";
const nfcpage = () => {
return (
<>
<Button
id = "scanButton"
>
Press to test NFC
</Button>
</>
);
};
export default nfcpage;
I want the scanButton code to run when the button is pressed. In other words to make scanButton into a function that can be called by my button via onClick{}.
Thank you
I was able to fix this by creating an async function from the sample code and passing that to onClick in the button component

Manually setting Desktop vesion in React

I have a custom Hook useWindowSize that determines whether there is a Mobile or Desktop environment. This is fine for most cases except when a mobile user wants to access the desktop version on his/her phone. I have a button to manually override the current windowsize but am not sure how to approach this.
Here I determine the opposite of the loaded windowsize but how can I switch and reload to the appropriate mode on click?
I will need this mode to stay afterwards even if the window is resized to keep the components linked to either mobile or desktop.
import "./styles.css";
import "./app.scss";
import useWindowSize from "./useWindowSize";
export default function App() {
const windowSize = useWindowSize();
const otherMode = windowSize <= "useMobileVersion" ? "useDesktopVersion" : "useDesktopVersion";
return (
<div className="App">
<p>Right now you are in {windowSize} mode. <button onClick={() => setPageMode("otherMode")}>
Switch to {otherMode} mode
</button>
</p>
</div>
);
}
The codesandbox is here.
The custom Hook is her:
import { useState, useEffect } from "react";
//a Util function that will convert the absolute width into breakpoints
function getBreakPoint(windowWidth) {
if (windowWidth) {
if (windowWidth < 420) {
return "useMobileVersion";
} else {
return "useDesktopVersion";
}
} else {
return "useDesktopVersion";
}
}
function useWindowSize() {
const isWindowClient = typeof window === "object";
const [windowSize, setWindowSize] = useState(
isWindowClient ? getBreakPoint(window.innerWidth) : undefined
);
useEffect(() => {
//a handler which will be called on change of the screen resize
function setSize() {
setWindowSize(getBreakPoint(window.innerWidth));
}
if (isWindowClient) {
//register the window resize listener
window.addEventListener("resize", setSize);
//unregister the listener
return () => window.removeEventListener("resize", setSize);
}
}, [isWindowClient, setWindowSize]);
return windowSize;
}
export default useWindowSize;

How to link to a show view from an index using react hooks with firestore data

I am trying to figure out how to define a link to reference that can use a firebase document id to link to a show view for that document. I can render an index. I cannot find a way to define a link to the document.
I've followed this tutorial - which is good to get the CRUD steps other than the show view. I can find other tutorials that do this with class components and the closest I've been able to find using hooks is this incomplete project repo.
I want to try and add a link in the index to show the document in a new view.
I have an index with:
const useBlogs = () => {
const [blogs, setBlogs] = useState([]); //useState() hook, sets initial state to an empty array
useEffect(() => {
const unsubscribe = Firebase
.firestore //access firestore
.collection("blog") //access "blogs" collection
.where("status", "==", true)
.orderBy("createdAt")
.get()
.then(function(querySnapshot) {
// .onSnapshot(snapshot => {
//You can "listen" to a document with the onSnapshot() method.
const listBlogs = querySnapshot.docs.map(doc => ({
//map each document into snapshot
id: doc.id, //id and data pushed into blogs array
...doc.data() //spread operator merges data to id.
}));
setBlogs(listBlogs); //blogs is equal to listBlogs
});
return
// () => unsubscribe();
}, []);
return blogs;
};
const BlogList = ({ editBlog }) => {
const listBlog = useBlogs();
return (
<div>
{listBlog.map(blog => (
<Card key={blog.id} hoverable={true} style={{marginTop: "20px", marginBottom: "20px"}}>
<Title level={4} >{blog.title} </Title>
<Tag color="geekblue" style={{ float: "right"}}>{blog.category} </Tag>
<Paragraph><Text>{blog.caption}
</Text></Paragraph>
<Link to={`/readblog/${blog.id}`}>Read</Link>
<Link to={`/blog/${blog.id}`}>Read</Link>
</Card>
))}
</div>
);
};
export default BlogList;
Then I have a route defined with:
export const BLOGINDEX = '/blog';
export const BLOGPOST = '/blog/:id';
export const NEWBLOG = '/newblog';
export const EDITBLOG = '/editblog';
export const VIEWBLOG = '/viewblog';
export const READBLOG = '/readblog/:id';
I can't find a tutorial that does this with hooks. Can anyone see how to link from an index to a document that I can show in a different page?
I did find this code sandbox. It looks like it is rendering a clean page in the updateCustomer page and using data from the index to do it - but the example is too clever for me to unpick without an explanation of what's happening (in particular, the updateCustomer file defines a setCustomer variable, by reference to useForm - but there is nothing in useForm with that definition. That variable is used in the key part of the file that tries to identify the data) - so I can't mimic the steps.
NEXT ATTEMPT
I found this blog post which suggests some changes for locating the relevant document.
I implemented these changes and while I can print the correct document.id on the read page, I cannot find a way to access the document properties (eg: blog.title).
import React, { useHook } from 'react';
import {
useParams
} from 'react-router-dom';
import Firebase from "../../../firebase";
import BlogList from './View';
function ReadBlogPost() {
let { slug } = useParams()
// ...
return (
<div>{slug}
</div>
)
};
export default ReadBlogPost;
NEXT ATTEMPT:
I tried to use the slug as the doc.id to get the post document as follows:
import React, { useHook, useEffect } from 'react';
import {
useParams
} from 'react-router-dom';
import Firebase from "../../../firebase";
import BlogList from './View';
function ReadBlogPost() {
let { slug } = useParams()
// ...
useEffect(() => {
const blog =
Firebase.firestore.collection("blog").doc(slug);
blog.get().then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
doc.data();
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});
});
return (
<div>{blog.title}
</div>
)
};
export default ReadBlogPost;
It returns an error saying blog is not defined. I also tried to return {doc.title} but I get the same error. I can see all the data in the console.
I really can't make sense of coding documentation - I can't figure out the starting point to decipher the instructions so most things I learn are by trial and error but I've run out of places to look for inspiration to try something new.
NEXT ATTEMPT
My next attempt is to try and follow the lead in this tutorial.
function ReadBlogPost(blog) {
let { slug } = useParams()
// ...
useEffect(() => {
const blog =
Firebase.firestore.collection("blog").doc(slug);
blog.get().then(function(doc) {
if (doc.exists) {
doc.data()
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});
},
[blog]
);
return (
<div><Title level={4} > {blog.title}
</Title>
<p>{console.log(blog)}</p>
</div>
)
};
export default ReadBlogPost;
When I try this, the only odd thing is that the console.log inside the useEffect method gives all the data accurately, but when I log it form inside the return method, I get a load of gibberish (shown in the picture below).
NEXT ATTEMPT
I found this tutorial, which uses realtime database instead of firestore, but I tried to copy the logic.
My read post page now has:
import React, { useHook, useEffect, useState } from 'react';
import {
useParams
} from 'react-router-dom';
import Firebase from "../../../firebase";
import BlogList from './View';
import { Card, Divider, Form, Icon, Input, Switch, Layout, Tabs, Typography, Tag, Button } from 'antd';
const { Paragraph, Text, Title } = Typography;
const ReadBlogPost = () => {
const [loading, setLoading] = useState(true);
const [currentPost, setCurrentPost] = useState();
let { slug } = useParams()
if (loading && !currentPost) {
Firebase
.firestore
.collection("blog")
.doc(slug)
.get()
.then(function(doc) {
if (doc.exists) {
setCurrentPost(...doc.data());
console.log("Document data:", doc.data());
}
}),
setLoading(false)
}
if (loading) {
return <h1>Loading...</h1>;
}
return (
<div><Title level={4} >
{currentPost.caption}
{console.log({currentPost})}
</Title>
</div>
)
};
export default ReadBlogPost;
Maybe this blog post is old, or maybe it's to do with it using .js where I have .jsx - which I think means I can't use if statements, but I can't get this to work either. The error says:
Line 21:9: Expected an assignment or function call and instead saw
an expression no-unused-expressions
It points to the line starting with Firebase.
I got rid of all the loading bits to try and make the data render. That gets rid of the above error message for now. However, I still can't return the values from currentPost.
It's really odd to me that inside the return statement, I cannot output {currentPost.title} - I get an error saying title is undefined, but when I try to output {currentPost} the error message says:
Error: Objects are not valid as a React child (found: object with keys
{caption, category, createdAt, post, status, title}). If you meant to
render a collection of children, use an array instead.
That makes no sense! I'd love to understand why I can log these values before the return statement, and inside the return statement, I can log them on the object but I cannot find how to log them as attributes.
First of all: is your useBlog() hook returning the expected data? If so, all you need to do is define your <Link/> components correctly.
<Link
// This will look like /readblog/3. Curly braces mean
// that this prop contains javascript that needs to be
// evaluated, thus allowing you to create dynamic urls.
to={`/readblog/${blog.id}`}
// Make sure to open in a new window
target="_blank"
>
Read
</Link>
Edit: If you want to pass the data to the new component you need to set up a store in order to avoid fetching the same resource twice (once when mounting the list and once when mounting the BlogPost itself)
// Define a context
const BlogListContext = React.createContext()
// In a top level component (eg. App.js) define a provider
const App = () => {
const [blogList, setBlogList] = useState([])
return (
<BlogListContext.Provider value={{blogList, setBlogList}}>
<SomeOtherComponent/>
</BlogListContext.Provider>
)
}
// In your BlogList component
const BlogList = ({ editBlog }) => {
const { setBlogList } = useContext(BlogListContext)
const listBlog = useBlogs()
// Update the blog list from the context each time the
// listBlog changes
useEffect(() => {
setBlogList(listBlog)
}, [listBlog])
return (
// your components and links here
)
}
// In your ReadBlog component
const ReadBlogComponent = ({ match }) => {
const { blogList } = useContext(BlogListContext)
// Find the blog by the id from params.
const blog = blogList.find(blog => blog.id === match.params.id) || {}
return (
// Your JSX
)
}
There are other options for passing data as well:
Through url params (not recommended).
Just pass the ID and let the component fetch its own data on mount.
I found an answer that works for each attribute other than the timestamp.
const [currentPost, setCurrentPost] = useState([]);
There is an empty array in the useState() initialised state.
In relation to the timestamps - I've been through this hell so many times with firestore timestamps - most recently here. The solution that worked in December 2019 no longer works. Back to tearing my hair out over that one...

How to implement barcode scanner in reactjs application?

I am developing an Order Scan web application, and the challenge I'm facing is that, if barcode matches, where I'm going to receive data in my react.js application. I'll be using a barcode scanner device, so can I use this npm package https://www.npmjs.com/package/react-barcode-reader. If so, how to implement it in my react app?
I have searched the web for answers. I couldn't find anything to my specific problem in react.js.
A barcode scanner is simply an input device. Just think of it as a keyboard.
You may receive its inputs via any TextInputs component.
If your barcode scanner is programmed to terminate with "\n", then the TextInput will also trigger onSubmit event.
I would recommend using the React Barcode Scanner NPM package. A simple demonstration is on that site. You can use their Barcode Scanner component:
<BarcodeReader
onError={handleError}
onScan={handleScan}
/>
You can apply that component in where you want the user to perform the scan. You will just need to make a handleScan and handleError function.
Examples:
const [scanData, setScanData] = useState()
const handleScan = (data) => {
setScanData(data)
}
const handleError = (err) => console.error(err)
The data will be stored in the scanData variable. Hope you find this helpful.
This is a very simple example for barcode reading in React, using simple vanilla javascript:
This works using timeframe to detect barcode readings. You can easily change it for endline codes (you won't need the timeout)
import { useEffect, useState } from "react";
import "./App.css";
function App() {
const [barcodeRead, setBarcodeRead] = useState("");
const barcode = {
timing: 1000,
data: "",
};
const barcodeReaded = () => {
if (barcode.data.length > 1) {
setBarcodeRead(barcode.data);
} else {
barcode.data = "";
}
};
let timeout = setTimeout(barcodeReaded, 500);
useEffect(() => {
window.addEventListener("keypress", (e) => {
console.log(e.key);
console.log(e.timeStamp);
if (barcode.data.length === 0 || e.timeStamp - barcode.timing < 200) {
barcode.data += e.key;
barcode.timing = e.timeStamp;
clearTimeout(timeout);
timeout = setTimeout(barcodeReaded, 500);
} else {
barcode.data = "";
}
console.log(barcode);
});
}, []);
return (
<div className="App">
<div>Readed: {barcodeRead}</div>
</div>
);
}
export default App;

Resources