quagga-react barcode scanner - reactjs

Essentially I get the demo to work save for the actual scanning. i.e. camera is on etc. Not sure what I am missing...
Here is my code.
App.js file:
import React, { Component } from 'react';
import Scanner from './Scanner';
import Result from './Result';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scanning: false,
results: [],
};
this._scan = this._scan.bind(this);
this._onDetected = this._onDetected.bind(this);
}
_scan() {
this.setState({ scanning: !this.state.scanning });
}
_onDetected(result) {
this.setState({ results: this.state.results.concat([result]) });
}
render() {
return (
<div>
<button onClick={this._scan}>{this.state.scanning ? 'Stop' : 'Start'}</button>
<ul className="results">
{this.state.results.map(result => {
<Result key={result.codeResult.code} result={result} />;
})}
</ul>
{this.state.scanning ? <Scanner onDetected={this.state._onDetected} /> : null}
</div>
);
}
}
Scanner.js file:
import React, { Component } from 'react';
import Quagga from 'quagga';
export default class Scanner extends Component {
constructor(props) {
super(props);
this._onDetected = this._onDetected.bind(this);
}
componentDidMount() {
Quagga.init(
{
inputStream: {
type: 'LiveStream',
constraints: {
width: 640,
height: 480,
facingMode: 'environment', // or user
},
},
locator: {
patchSize: 'medium',
halfSample: true,
},
numOfWorkers: 2,
decoder: {
readers: ['upc_reader'],
},
locate: true,
},
function(err) {
if (err) {
return console.log(err);
}
Quagga.start();
}
);
Quagga.onDetected(this._onDetected);
}
componentWillUnmount() {
Quagga.offDetected(this._onDetected);
}
_onDetected(result) {
this.props.onDetected(result);
}
render() {
return <div id="interactive" className="viewport" />;
}
}
Result.js file:
import React, { Component } from 'react';
export default class Result extends Component {
render() {
const result = this.props.result;
if (!result) {
return null;
}
return (
<li>
{result.codeResult.code} [{result.codeResult.format}]
</li>
);
}
}
Thanks my friends!

You may want to change the reader type, which is code_128_reader by default.
Most barcodes used in supermarkets for example follow the EAN specification (at least where I live), so you can put this in Scanner.js to change to an ean_reader:
decoder: {
readers: ["ean_reader"]
},
where Quagga is initiated.
A list of readers can be found here: Quagga documentation.
If this doesn't work, I would advise to try other reader / barcode combinations.

The documentation says that in Node you should use numOfWorkers: 0
https://serratus.github.io/quaggaJS/#node-example

add /* eslint-disable */ in to return .
{
/* eslint-disable */
this.state.results.map(result => {
<Result key={result.codeResult.code} result={result} />;
})}
</ul>

Might be too late to answer, will leave it here in case anyone would be interested.
I was able to make it work. There were few issues I had to resolve:
Applied different decoder as rpld suggested:
decoder: {
readers: ["ean_reader"]
},
Fix TypeError: this.props.onDetected is not a function. In App.js adjusted the following line:
From:
{this.state.scanning ? <Scanner onDetected={this.state._onDetected} /> : null}
To:
{this.state.scanning ? <Scanner onDetected={(result) => this._onDetected(result)} /> : null}
I also used Quagga2, but don't know if it makes any difference in this case.
Leaving full version of working code, just in case.
App.js:
import React, { Component } from 'react';
import Scanner from './Scanner';
import Result from './Result';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scanning: false,
results: []
};
this._scan = this._scan.bind(this);
this._onDetected = this._onDetected.bind(this);
}
_scan() {
this.setState({ scanning: !this.state.scanning });
}
_onDetected(result) {
this.setState({ results: this.state.results.concat([result]) });
}
render() {
return (
<div>
<button onClick={this._scan}>{this.state.scanning ? 'Stop' : 'Start'}</button>
<ul className="results">
{this.state.results.map((result, idx) => {
return (<Result key={result.codeResult.code} result={result} />)
})}
</ul>
{this.state.scanning ? <Scanner onDetected={(result) => this._onDetected(result)} /> : null}
</div>
);
}
}
Scanner.js:
import React, { Component } from 'react';
import Quagga from '#ericblade/quagga2';
export default class Scanner extends Component {
constructor(props) {
super(props);
this._onDetected = this._onDetected.bind(this);
}
componentDidMount() {
Quagga.init(
{
inputStream: {
type: 'LiveStream',
constraints: {
width: 640,
height: 480,
facingMode: 'environment', // or user
},
},
locator: {
patchSize: 'medium',
halfSample: true,
},
numOfWorkers: 0,
decoder: {
readers: ['ean_reader'],
},
locate: true,
},
function(err) {
if (err) {
return console.log(err);
}
Quagga.start();
}
);
Quagga.onDetected(this._onDetected);
}
componentWillUnmount() {
Quagga.offDetected(this._onDetected);
}
_onDetected(result) {
this.props.onDetected(result);
}
render() {
return <div id="interactive" className="viewport" />;
}
}
Result.js (not touched at all):
import React, { Component } from 'react';
export default class Result extends Component {
render() {
const result = this.props.result;
if (!result) {
return null;
}
return (
<li >
{result.codeResult.code} [{result.codeResult.format}]
</li>
);
}
}

Related

My checkbox is not changing from check or uncheck, but I can see that state value is changing, what's going on?

So when I run this and check the checkbox, I can see the values changing in the state, but why is the checkbox control not changing its status from check/uncheck? I know the render() method is being hit as well. Why, oh why, Gods of code? Lost in hours of figuring out what's wrong and I'm lost!
bob-Todos.js FILE
class Todo extends React.Component {
constructor(param) {
super();
this.state = {
id: param.data.id,
text: param.data.text,
completed: param.data.completed,
onMyChange: param.OnChange,
};
}
render() {
console.log("In TODO Render");
return (
<div>
<p>
<input
type="checkbox"
onChange={() => {
this.state.onMyChange(this.state.id);
}}
checked={this.state.completed}
/>
{this.state.text}
</p>
</div>
);
}
}
export default Todo;
Bob-App.js FILE
import React, { Component } from "react";
import Todo from "./bob-Todo";
import todoData from "../data/bob-todosData";
class App extends Component {
constructor() {
super();
this.state = { data: todoData };
this.OnChange = this.OnChange.bind(this);
}
OnChange(myId) {
this.setState((prev) => {
let updatedTodos = prev.data.map((todo) => {
if (todo.id === myId) {
todo.completed = !todo.completed;
}
return todo;
});
return { data: updatedTodos };
});
console.log(this.state.data);
}
render() {
return this.state.data.map((item) => {
return <Todo key={item.id} data={item} OnChange={this.OnChange} />;
});
}
}
export default App;
bob-todosData.js FILE
const todosData = [
{
id: 1,
text: "take out the trash",
completed: true
},
{
id: 2,
text: "rest for a while and relax",
completed: false
},
{
id: 3,
text: "watch an online movie",
completed: true
}
]
export default todosData
index.js FILE
import React from 'react';
import ReactDOM from 'react-dom';
import AppBob from "./bobComponents/Bob-App";
ReactDOM.render(
<AppBob />, document.getElementById('root')
);
You don't need to assign your props to state in your Todo component
Just remove them and invoke the function also use those variables directly:
Then your component will be:
class Todo extends React.Component {
render() {
const {
data: {
id,
text,
completed,
},
OnChange, // <-- Should rename this to "onChange"
} = this.props;
console.log('In TODO Render');
return (
<div>
<p>
<input
type="checkbox"
onChange={() => {
OnChange(id);
}}
checked={completed}
/>
{text}
</p>
</div>
);
}
}
export default Todo;
Also, rename your OnChange function to onChange to enable js convention

react twilio video: first joiner screen black on participant join

i have made a twillio video app.i can show local video on Laptop website but when i join from another chrome tab or mobile phone chrome browser the video on laptop goes black and only one video is showing whereas both videos should show properly.i am following this tutorial
https://www.twilio.com/blog/build-a-custom-video-chat-app-with-react-and-twilio-programmable-video
here is my code
App.js
import './App.scss';
import React, {Component} from 'react';
import Room from './Components/Room';
const { connect } = require('twilio-video');
const Token = {"identity":"Jose Corkery","token":"...sioAMt4..."}
class App extends Component {
constructor(props) {
super(props)
this.state = {
identity: '',
room: null
}
this.inputRef = React.createRef();
this.joinRoom = this.joinRoom.bind(this);
this.returnToLobby = this.returnToLobby.bind(this);
this.updateIdentity = this.updateIdentity.bind(this);
this.removePlaceholderText = this.removePlaceholderText.bind(this)
}
async joinRoom() {
try {
// const response = Token
// const data = await response.json();
const room = await connect(Token.token, {
name: 'cool-room',
audio: true,
video: true
});
// alert(room)
this.setState({ room: room });
} catch(err) {
alert(err);
}
}
updateIdentity(event) {
this.setState({
identity: event.target.value
});
}
returnToLobby() {
this.setState({ room: null });
}
removePlaceholderText() {
this.inputRef.current.placeholder = '';
}
render() {
const disabled = this.state.identity === '' ? true : false;
return (
<div className="app">
{
this.state.room === null
? <div className="lobby">
<input
ref={this.inputRef}
onClick={this.removePlaceholderText}
placeholder="What's your name?"
onChange={this.updateIdentity}
/>
<button disabled = {disabled} onClick={this.joinRoom}>Join Room</button>
</div>
: <Room returnToLobby={this.returnToLobby} room={this.state.room} />
}
</div>
);
}
}
export default App;
Room.jsx
import React, { Component } from 'react';
import Participant from './Participant';
const { connect } = require('twilio-video');
class Room extends Component {
componentDidMount() {
this.props.room.on('participantConnected', participant => this.addParticipant(participant));
this.props.room.on('participantDisconnected', participant => this.removeParticipant(participant));
window.addEventListener("beforeunload", this.leaveRoom);
}
componentWillUnmount() {
this.leaveRoom();
}
addParticipant(participant) {
console.log(`${participant.identity} has joined the room.`);
alert(`+ Participant : ${participant.identity}`)
this.setState({
remoteParticipants: [...this.state.remoteParticipants, participant]
})
}
removeParticipant(participant) {
alert(`Leaving : ${participant.identity}`)
console.log(`${participant.identity} has left the room`);
this.setState({
remoteParticipants: this.state.remoteParticipants.filter(p => p.identity !== participant.identity)
});
}
leaveRoom() {
this.props.room.disconnect();
this.props.returnToLobby();
}
constructor(props) {
super(props)
this.state = {
remoteParticipants: Array.from(this.props.room.participants.values())
}
this.leaveRoom = this.leaveRoom.bind(this);
}
render() {
return (
<div className="room">
<div className="participants">
<Participant
key={this.props.room.localParticipant.identity}
localParticipant="true"
participant={this.props.room.localParticipant} />
{
this.state.remoteParticipants.map(participant =>
<Participant key={participant.identity} participant={participant} />
)
}
</div>
<button id="leaveRoom" onClick={this.leaveRoom}>Leave Room</button>
</div>
);
}
}
export default Room
Participant.jsx
import React, { Component } from 'react';
import Track from './Track';
const { connect } = require('twilio-video');
class Participant extends Component {
componentDidMount() {
if (!this.props.localParticipant) {
this.props.participant.on('trackSubscribed', track => this.addTrack(track));
}
}
constructor(props) {
super(props);
const existingPublications = Array.from(this.props.participant.tracks.values());
const existingTracks = existingPublications.map(publication => publication.track);
const nonNullTracks = existingTracks.filter(track => track !== null)
this.state = {
tracks: nonNullTracks
}
}
addTrack(track) {
this.setState({
tracks: [...this.state.tracks, track]
});
}
render() {
return (
<div className="participant" id={this.props.participant.identity}>
<div className="identity">{this.props.participant.identity}</div>
{
this.state.tracks.map(track =>
<Track key={track} filter={this.state.filter} track={track}/>)
}
</div>
);
}
}
export default Participant
Track.jsx
import React, { Component } from 'react';
class Track extends Component {
componentDidMount() {
if (this.props.track !== null) {
const child = this.props.track.attach();
this.ref.current.classList.add(this.props.track.kind);
this.ref.current.appendChild(child)
}
}
constructor(props) {
super(props)
this.ref = React.createRef();
}
render() {
return (
<div className="track" ref={this.ref}>
</div>
)
}
}
export default Track
demo:https://android-anime.web.app
i have only two video events onJoin and onLeave do i need additional events ?
what is the solution? if your solution works i will award you best answer.Thanks !!

'delTodo' is not defined. React (line 51)

Error:
'delTodo' is not defined. React (line 51)
I am new to React. Here is the code; what did I do wrong?
import React, { Component } from 'react';
import Todos from './components/Todos';
import markComplete from './components/Todos'
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
todos: [
{
key: 1,
title: 'Take out the trash',
completed:false
},
{`enter code here`
key: 2,
title: 'Dinner with wife',
completed:true`enter code here`
},
{
key: 3,
title: 'Meeting with boss',
completed:false
}
]
}
}
asd = () =>{
}
// Toggle Complete
markComplete = (key) => {
this.setState({ todos: this.state.todos.map(todo=> {
if(todo.key === key) {
todo.completed = !todo.completed
}
return todo;
}) });
}
//Delete Todo
delTodo = (key) => {
console.log(key)
}
render() {
return (
<div className="App">
<Todos todos={this.state.todos} markComplete={markComplete}
delTodo={delTodo} />
</div>
);
}
}
export default App;
If you're using a class component, you need to use the this keyword when you refer to class attributes (state, methods, etc.). So the method should be this.delTodo:
return (
<div className="App">
<Todos
todos={this.state.todos}
markComplete={this.markComplete}
delTodo={this.delTodo}
/>
</div>
)

Problem with make query in correct way using typescript, react and graphql

excuse me for that probably stupid question but this is my first steps with graphql and react. I try to create component where inside is GraphQL query, and incoming props. Props is a query which should by pass into GraphQL query. I know I do something wrong but I don't know what. I add everything like client with apollo provider into my app component structure.
On a main page (index.js) I have simply layout like:
import Layout from "../components/layout"
import SearchForm from "../components/searchForm"
export default function Home() {
return (
<Layout pageTitle="React App" headerTitle="Search repositories on Github">
<SearchForm repositoryNameDefaultValue='' />
</Layout>
);
}
then I have component called searchForm:
import { Component, ChangeEvent } from "react";
import Input from "./input";
import Button from "./button";
import style from "./searchForm.module.scss";
import FindRepositoryResults from "./test";
interface IMyComponentErrors {
repositoryNameError: string;
}
interface IMyComponentProps {
repositoryNameDefaultValue: string;
}
interface IMyComponentState {
repositoryName: string;
formIsSend: boolean;
errors: IMyComponentErrors;
}
const validateForm = (errors: IMyComponentErrors): boolean => {
let valid = true;
Object.values(errors).forEach((val) => val.length > 0 && (valid = false));
return valid;
};
const validRepositoryNameRegex = RegExp(/^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$/i);
export default class SignUpFormContainer extends Component<
IMyComponentProps,
IMyComponentState
> {
constructor(props: IMyComponentProps) {
super(props);
this.state = {
repositoryName: this.props.repositoryNameDefaultValue,
formIsSend: false,
errors: {
repositoryNameError: "",
}
};
this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.handleClearForm = this.handleClearForm.bind(this);
this.handleChangeRepositoryName = this.handleChangeRepositoryName.bind(this);
}
handleChangeRepositoryName(event: ChangeEvent<HTMLInputElement>): void {
event.preventDefault();
const { value } = event.target;
let errors = this.state.errors;
if (!validRepositoryNameRegex.test(value)) {
errors.repositoryNameError = "Invalid repository name";
} else if (!value) {
errors.repositoryNameError = "Repository name is required";
} else {
errors.repositoryNameError = "";
}
this.setState({ errors, repositoryName: value });
}
handleClearForm() {
this.setState({
repositoryName: "",
formIsSend: false
});
}
handleFormSubmit(event) {
event.preventDefault();
const { repositoryName } = this.state;
let errors = this.state.errors;
if (!repositoryName) {
errors.repositoryNameError = "Repository name is required";
}
this.setState({ errors });
if (!validateForm(this.state.errors)) {
return;
} else {
this.setState({ formIsSend: true });
}
}
render() {
const { errors } = this.state;
return (
<div>
{ !this.state.formIsSend ? (
<form
aria-label="Search repositories by name"
autoComplete="off"
onSubmit={this.handleFormSubmit}
className = {style.formSearchRepository}
>
<Input
type={"text"}
title={"Repository name:"}
name={"repositoryName"}
placeholder={"Enter name of repository"}
value={this.state.repositoryName}
error={errors.repositoryNameError.length > 0}
errorMessage={errors.repositoryNameError}
onChange={this.handleChangeRepositoryName}
required
/>
<Button
onClick={this.handleFormSubmit}
title={"Search repository in Github by name"}
children={"Search"}
/>
</form>
) : <FindRepositoryResults repositoryName={this.state.repositoryName}/>}
</div>
);
}
}
and last one that more problematic where is query:
import React from "react";
import { gql, useQuery } from "#apollo/client";
const SEARCH_REPOSITORY = gql`
query findRepositories($query: String!) {
search(first: 10, query: $query, type: REPOSITORY) {
nodes {
... on Repository {
name,
owner {
login
}
primaryLanguage {
name
},
stargazers {
totalCount
},
stargazerCount,
languages(first: 20, orderBy: {field: SIZE, direction: ASC} ) {
totalCount
nodes {
name
}
},
issues {
totalCount
}
shortDescriptionHTML,
updatedAt,
watchers {
totalCount
}
}
}
}
}
`;
interface IFindRepositoryComponentProps {
repositoryName: string;
}
interface IFindRepositoryComponentState {
detailsAreOpen: boolean;
}
interface RepositoryData {
data: any;
}
interface RepositoryVars {
query: string;
}
export default class FindRepositoryResults extends React.Component<IFindRepositoryComponentProps, IFindRepositoryComponentState> {
constructor(props: IFindRepositoryComponentProps) {
super(props);
this.state = { detailsAreOpen: false };
this.showDetails = this.showDetails.bind(this);
}
showDetails() {
this.setState(state => ({
detailsAreOpen: !state.detailsAreOpen
}));
}
render() {
const { loading, data, error } = useQuery<any, RepositoryVars>(
SEARCH_REPOSITORY ,
{ variables: { query: this.props.repositoryName } }
);
return (
<section>
<h3>Results</h3>
{loading ? (
<p>Loading ...</p>
) : error ? (<p>Error {error}</p>) : (
<div>
{ data.search.nodes.length == 0 ? (<p>No results found.</p>) : data && data.search.nodes.map((repo) => (
<div>
<p>Name: {repo.name}</p>
<p>Owner: {repo.owner.login}</p>
<p>Number of stars (total): {repo.stargazerCount}</p>
<p>Primary language: {repo.primaryLanguage.name}</p>
<button onClick={this.showDetails}>{this.state.detailsAreOpen ? 'Show less' : 'Show more'}</button>
<div>
Details:
{repo.issues.totalCount}
{repo.languages.totalCount}
{repo.shortDescriptionHTML}
{repo.stargazers.totalCount}
{repo.updatedAt}
{repo.watchers.totalCount}
</div>
</div>
))}
</div>
)}
</section>
);
}
}
In this component above I made query but I don't get results. I'm not sure but is mismatching of version (DOM Rendering), I have a problem to do this correctly together with typescript, react and apollo. I'll happy if any one can show me correct way and example how this should be done. Thank you
I haven't used typescript, but React hooks and GraphQL. So you made the query but you don't get any results? If the query is executed then there should be a result or an error. If it goes that far it could help to download the Apollo-Graphql plugin (to Google Chrome perhaps?).
I would try the query in the graphi-ql playground for example.
Also, variable-name query inside of your query is a bit confusing.
Best, J

Render Clappr player in ReactJS

I'm using Clappr player with ReactJS.
I want Clappr player component appear and destroy when I click to a toggle button. But it seems like when Clappr player is created, the entire page has reload (the toggle button dissapear and appear in a blink). So here is my code:
ClapprComponent.js
import React, { Component } from 'react'
import Clappr from 'clappr'
class ClapprComponent extends Component {
shouldComponentUpdate(nextProps) {
let changed = (nextProps.source != this.props.source)
if (changed) {
this.change(nextProps.source)
}
return false
}
componentDidMount() {
this.change(this.props.source)
}
componentWillUnmount() {
this.destroyPlayer()
}
destroyPlayer = () => {
if (this.player) {
this.player.destroy()
}
this.player = null
}
change = source => {
if (this.player) {
this.player.load(source)
return
}
const { id, width, height } = this.props
this.player = new Clappr.Player({
baseUrl: "/assets/clappr",
parent: `#${id}`,
source: source,
autoPlay: true,
width: width,
height: height
})
}
render() {
const { id } = this.props
return (
<div id={id}></div>
)
}
}
export default ClapprComponent
Video.js
import React, { Component } from 'react'
import { Clappr } from '../components'
class VideoList extends Component {
constructor() {
super()
this.state = {
isActive: false
}
}
toggle() {
this.setState({
isActive: !this.state.isActive
})
}
render() {
const boxStyle = {
width: "640",
height: "360",
border: "2px solid",
margin: "0 auto"
}
return (
<div>
<div style={boxStyle}>
{this.state.isActive ?
<Clappr
id="video"
source="http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/sl.m3u8"
width="640"
height="360" />
: ''}
</div>
<button class="btn btn-primary" onClick={this.toggle.bind(this)}>Toggle</button>
</div>
)
}
}
export default VideoList
Anyone can explain why? And how to fix this problem?
Edit 1: I kind of understand why the button is reload. It's because in index.html <head>, I load some css. When the page is re-render, it load the css first, and then execute my app.min.js. The button doesn't reload in a blink if I move the css tags under the <script src="app.min.js"></script>.
But it doesn't solve my problem yet. Because the css files have to put in <head> tags. Any help? :(
Here you have a running (jsbin link) example. I simplified a little bit and it still shows your main requirement:
class ClapprComponent extends React.Component {
componentDidMount(){
const { id, source } = this.props;
this.clappr_player = new Clappr.Player({
parent: `#${id}`,
source: source
});
}
componentWillUnmount() {
this.clappr_player.destroy();
this.clappr_player = null;
}
render() {
const { id } = this.props;
return (
<div>
<p>Active</p>
<p id={id}></p>
</div>
);
}
}
class NotActive extends React.Component {
render() {
return (
<p>Not Active</p>
);
}
}
class App extends React.Component {
constructor(props){
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
isActive: false
}
}
toggle() {
this.setState({
isActive: !this.state.isActive
})
}
render() {
return (
<div>
<h1>Clappr React Demo</h1>
{ this.state.isActive ?
<ClapprComponent
id="video"
source="http://www.html5videoplayer.net/videos/toystory.mp4"
/> :
<NotActive />}
<button onClick={this.toggle}>Toggle</button>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
Also make sure to rename the button class property to className.
Maybe you can work from here to find your exact problem? Hope that helps.
In Clappr's documentation I found a like about how to use clappr with reactjs

Resources