Run tesseract.js OCR onFileUpload and extract text - reactjs

I think the title is self-explanatory. What am I doing wrong below? What I want to achieve is getting the text out of a photo, right after the user selects a photo.
The error I get is:
createWorker.js:173 Uncaught Error: RuntimeError: null function or function signature mismatch
What am I doing wrong?
const { createWorker } = require("tesseract.js");
const [file,setFile] = useState();
const worker = createWorker({
logger: (m) => console.log(m),
});
const doOCR = async (image) => {
await worker.load();
await worker.loadLanguage("eng");
await worker.initialize("eng");
const {
data: { text },
} = await worker.recognize(image);
// } = await worker.recognize('https://tesseract.projectnaptha.com/img/eng_bw.png');
console.log(text);
setOcr(text);
};
const [ocr, setOcr] = useState("Recognizing...");
useEffect(() => {
file ? doOCR(file) : console.log('no file selected yet!');
}, [file]);
const getFile = (e) => {
console.log("Upload event:", e);
if (e) {
if (Array.isArray(e)) setFile(e[0]);
setFile(e)
}
}
....
<p>{ocr}</p> /* this only displays "Recognizing..." */
<Form.Item
name="uploadedPhoto"
label="Upload your photo scan"
getValueFromEvent={getFile}
// rules={[{ required: true }]}>
<Input type="file"
// onChange={onImageUpload}
/>
</Form.Item>

Solved it by doing it like this instead of the above (I applied the function to the onChange of the Input itself, not the Form.Item element)
const handleFileSelected = (e) => {
const files = Array.from(e.target.files);
setFile(files[0]);
};
<Input type="file" onChange={handleFileSelected} />

Related

react state cant delete first letter

I have this code that edit data, it works properly when adding text but removing all letters will not remove first letter.
export const Edit = (props: any) => {
const { initial } = usefetchEditUserType(props)
return (
<>
<CreateUpdate
title="Edit User Type"
useMutationHooks={useEditRole(props.id)} /** Change this */
editPermission={true}
value={initial} -->
id={props.id}
/>
<ListAssignUserAccount {...props} />
</>
);
};
CreateUpdate
const { inputValidation, handleOnChange, handleOnClickSubmit, data } = useMutationHooks;
<CardContent >
<TextField
required
//...omitted code
onChange={(e: any) => handleOnChange(e)}
error={inputValidation['input']}
helperText={inputValidation['input'] ? "Required*" : ""}
value={ data ? data : value } --> value from Edit component
/>
</CardContent>
useEditRole
export const useEditRole = (id: number) => {
const notify = useNotify()
const [inputValidation, setInputValidation] = useState({input: false, button: true})
const [data, setData] = useState("")
const handleOnClickSubmit = async () => {
await fetchCreateRole(data, "PUT", id).then((res: any) => {
notify("Successfully Updated!")
});
}
const handleOnChange = (e: any) => {
if(e.target.value) {
setData(e.target.value )
setInputValidation({ input: false, button: false})
} else {
setInputValidation({ input: true, button: true})
}
}
return { inputValidation, handleOnChange, handleOnClickSubmit, data, setData }
}
console logging seems working but in text field is not getting the changes input status. Im trying way another but then deleting in input field brings back the original or the default value

Handle upload multiple files in Dragger ant design component react js

i'm trying upload multiple file with Dragger of ant design, but when I upload multiple files the onChange event is also called multiple times, it causes duplicate files
const handleChange = ({ fileList }) => {
console.log(fileList);
setFileList(fileList.filter(file => file.status !== "error"));
var notUploadYet = fileList.reduce((accumulator, file) => {
if (!fileUploaded.find(x => x.name === file.name)) {
accumulator.push(file);
}
return accumulator;
}, [])
const handleUpload = async () => {
try {
for await (const file of notUploadYet) {
const typeMedia = file.type.split('/')[0]
var nameOnCloud = typeMedia === "video" ? `videos/${file.name + v4()}` : `images/${file.name + v4()}`
const storageRef = ref(storage, nameOnCloud);
await uploadBytes(storageRef, file.originFileObj)
console.log('upload success')
try {
const link = await getDownloadURL(storageRef)
setFileUploaded([...fileUploaded,
{
name: file.name,
link: link,
nameOnCloud: nameOnCloud,
type: typeMedia
}
])
} catch (error) {
console.log(error)
}
}
} catch (error) {
console.log(error)
}
}
handleUpload()
}
<Dragger
listType="picture-card"
fileList={fileList}
beforeUpload={beforeUpload}
onPreview={handlePreview}
onChange={handleChange}
onRemove={handleOnRemove}
multiple={true}
>
<AiOutlineUpload style={{ 'fontSize': 30 }} />
<div className="uploadText">
<p>Kéo và thả ở đây hoặc click để chọn</p>
</div>
</Dragger>
I want the onChange event to be called only once when I upload multiple files

Make an update request using Axios in React and Material UI

I am pretty new to React, and the only CRUD functionality I have done has been in MVC.net, so I am pretty lost here and none of the tutorials I am finding seem to be the situation I have going on...or maybe I am just misunderstanding them. The tips I got with my initial question helped, but I am still no getting it to work, so hopefully now I have supplies enough info to help other help me. I did no include all of the input fields because their are like 15 and it was just redundant.
I am pulling up the modal using this onClick event:
onClick={()=> {handleEditModal(item)}}
modalFunctions.js
// Modal Functionality
export function ModalFunctions() {
const [selectedRecord, setSelectedRecord] = useState([]);
const [openModal, setOpenModal] = useState(false);
const handleEditModal = item =>{
setOpenModal(true)
setSelectedRecord(item)
}
return {
selectedRecord,
setSelectedRecord,
openModal,
setOpenModal,
handleEditModal,
handleDetailModal
}
}
// Form Functionality
export function FormFunctions(validateOnChange = false, validate) {
const [values, setValues] = useState('');
const [errors, setErrors] = useState({});
const handleInputChange = e => {
const { name, value } = e.target
setValues({
...values,
[name]: value
})
if (validateOnChange)
validate({ [name]: value })
}
return {errors, handleInputChange, setErrors, setValues, values}
}
DataTable.js
// Imported Modal Functions
const {
selectedRecord,
openModal,
setOpenModal,
handleEditModal,
handleDetailModal
} = ModalFunctions();
const baseURL = 'http://localhost:8080/api/tanks';
// Fetch Data
useEffect(() => {
const fetchData = async () =>{
setLoading(true);
try {
const {data: response} = await axios.get(baseURL);
setTableData(response);
} catch (error) {
console.error(error.message);
}
setLoading(false);
};
fetchData();
}, [baseURL, setTableData, setLoading]);
// The Modal
return(
<Modal
title={ "Editing: " + (selectedRecord.tankName) }
openModal={openModal}
setOpenModal={setOpenModal}
>
<TankEdit
selectedRecord={selectedRecord}
setOpenModal={setOpenModal}
openModal={openModal}
/>
</Modal>
)
TankEdit.js
export function TankEdit(props) {
const { baseURL, openModal, selectedRecord, setOpenModal, setTableData } = props;
const validate = (fieldValues = item) => {
let temp = { ...errors }
if ('tankName' in fieldValues)
temp.tankName = fieldValues.tankName ? "" : "This field is required."
setErrors({
...temp
})
if (fieldValues === values)
return Object.values(temp).every(x => x === " ")
}
const {
values,
setValues,
errors,
setErrors,
handleInputChange,
} = FormFunctions(true, validate);
useEffect(() => {
if (selectedRecord !== null)
setValues({
...selectedRecord
})
}, [selectedRecord, setValues])
function editRecord() {
axios.put(`${baseURL}`, {
title: "Success",
body: "The record had been successfully updated"
}).then ((response) => {setTableData(response.data);})
}
const handleSubmit = e => {
e.preventDefault()
if (validate()) {
editRecord(values);
}
setOpenModal(false)
}
const item = values; // used for easier referencing (matches table item)
return (
<Form onSubmit={handleSubmit} open={openModal}>
<Grid>
<Controls.Input
name="tankName"
label="Tank Name"
value={item.tankName}
onChange={handleInputChange}
error={errors.tankName}
/>
</Grid>
<Grid>
<Controls.Button
type="submit"
text="Submit"
/>
<Controls.Button
text="Cancel"
color="default"
onClick={()=>{setOpenModal(false)}}
/>
</Grid>
</Form>
)
}
Input.js
export default function Input(props) {
const { error=null, label, name, onChange, value, ...other } = props;
return (
<TextField
variant="outlined"
label={label}
name={name}
value={value}
defaultValue=''
onChange={onChange}
{...other}
{...(error && {error:true,helperText:error})}
/>
)
}
My company is only wanting a Read and an Update function, since Creating and Deletion will be handled another ways, so this is my final hangup. I think I am close, but I am missing something.
Can anyone point me in the right direction?
THANKS!!!!
If you want to write an update request you would use axios.put to send the data to your back-end.
In your handleSubmit function you do:
let response = await axios.put('http://-------/api/tanks', { name: 'tank' });
(The second parameter is an object that needs to contain all the form data fields)
Also make sure you call e.preventDefault() in the handleSubmit function so you don't accidentally navigate elsewhere.
Then you will update your database or whatever using your back-end.
for update you should use put or patch method
and you should send id of item you want to update in request url.
I insert 2 example here.
this is for put:
const res = await axios.put('/api/article/123', {
title: 'Making PUT Requests with Axios',
status: 'published'
});
this is for patch:
const res = await axios.patch('/api/article/123', {
title: 'Making PUT Requests with Axios',
status: 'published'
});

How can I validate React input is not empty and valid email?

Right now the form is allowing empty and non valid email strings to be stored to my firestore.
In regular html input tag i know using required and type=email forces the validation.
Is there not something similar using Chakra Ui?
const SubscribeForm = () => {
const [input, setInput] = useState("");
const isError = input === ''
const handleSubmit = (e) => {
console.log("saved to firestore , input: " + input)
e.preventDefault();
saveEmail(input);
setInput("Thanks for subscribing!");
};
const saveEmail = async (input) => {
try {
const docRef = await addDoc(collection(db, "sub-emails"), {
email: input
});
console.log("Document written with ID: ", input);
} catch (e) {
console.error("Error adding document: " + input, e);
}
};
return (
<FormControl isRequired >
<Text paddingBottom="10px" fontSize="14px" color="white" > Get updated when site goes live!</Text>
<Input
isRequired
value={input}
onChange={(e) => setInput(e.target.value)} fontSize="13px" placeholder="example#gmail.com" bgColor="white" id='email' type='email' />
<Button
onClick={handleSubmit}
mt={4}
colorScheme='teal'
type='submit'
>
Submit
</Button>
</FormControl>
)
}
export default SubscribeForm
Doesn't seem like the isRequired and type='email' is working
Create a custom function like this:
const isValidEmail = /^[\w-\.]+#([\w-]+\.)+[\w-]{2,4}$/g;
const validateEmail = (e) => {
if(e.target?.value && e.target.value.match(isValidEmail)){
showNoValidEmail(false);
setInput(e.target.value)
}else{
showNoValidEmail(true);
}
}
Where showNoValidEmail it's a boolean state and can be used with a custom html message.
Now, in your handleSubmit you can do this:
const handleSubmit = (e) => {
console.log("saved to firestore , input: " + input)
e.preventDefault();
if(input && input.length && input.match(isValidEmail)){
saveEmail(input);
setInput("Thanks for subscribing!");
}else{
//show a error message or something like that
}
};

How to configure 'value' in the input field in React?

In React, I have a textbox with a Submit button that is visible when the user clicks 'Wave At Me' and is not visible after the user clicks 'Submit'. What do I put for value in the input tag? How do I get value should I can use it in the setFormText method? In the component class, value is below, but what is the equivalent for the function code?
<input type="text" value={this.state.value} onChange={this.handleChange} />
My code is below in the default App() function, currently the user is unable to change the text:
const [currentVisibility, setVisibility] = useState(false);
const [currentFormText, setFormText] = useState("");
//wave at me button just shows the form
const wave = async () => {
setVisibility(true);
console.log("form appears")
}
// I don't think it's correct to use changeValue function
const changeValue = async () => {
console.log("formed had some text");
}
const handleChange = async () => {
console.log("form was changed");
}
//the handle submit should read the value from the input field to use in the parameter string of the wave() function.
const handleSubmit = async () => {
try {
setVisibility(false);
const { ethereum } = window;
if (ethereum) {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);
let count = await wavePortalContract.getTotalWaves();
console.log("Retrieved total wave count...", count.toNumber());
//change to currentText instead of water bottle
const waveTxn = await wavePortalContract.wave("water bottle");
console.log("Mining...", waveTxn.hash);
await waveTxn.wait();
console.log("Mined -- ", waveTxn.hash);
count = await wavePortalContract.getTotalWaves();
console.log("Retrieved total wave count...", count.toNumber());
} else {
console.log("Ethereum object does not exist!");
}
} catch (error) {
console.log(error)
}
}
return {currentVisibility && (
<form onSubmit={handleSubmit}>
<label>
Message:
<input type="text" value="" onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
)}
The useState hook returns the state value and a setter function. So in your case, currentFormText is the state value and setFormText is the setter function. Thus, your input should read:
<input type="text" value={currentFormText} onChange={handleChange} />
If you do this, you'll notice you can't change the input's value. That's because React is now "controlling" the value of the input; in other words, React is now the "source of truth" for this input (rather than the browser/HTML itself). Because of this, you'll need to add to your handler function:
// we certainly don't need the `async` keyword here!
const handleChange = (event) => {
console.log("form was changed");
setFormText(event.target.value);
}
On form submit refresh the page, you need to put this code e.preventDefault(); in handleSubmitfunction !
When handleChange function call you need to set the input value in currentFormText state that's why you unable to change the text !
Try this code it's work for me
function App() {
const [currentVisibility, setVisibility] = useState(true);
const [currentFormText, setFormText] = useState("");
//wave at me button just shows the form
const wave = async () => {
setVisibility(true);
console.log("form appears")
}
const changeValue = async () => {
console.log("formed had some text");
}
const handleChange = async (value) => {
setFormText(value)
console.log("form was changed");
}
//the handle submit should read the value from the input field to use in the parameter string of the wave() function.
const handleSubmit = async (e) => {
try {
e.preventDefault();
setVisibility(false);
const { ethereum } = window;
if (ethereum) {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);
let count = await wavePortalContract.getTotalWaves();
console.log("Retrieved total wave count...", count.toNumber());
//change to currentText instead of water bottle
const waveTxn = await wavePortalContract.wave("water bottle");
console.log("Mining...", waveTxn.hash);
await waveTxn.wait();
console.log("Mined -- ", waveTxn.hash);
count = await wavePortalContract.getTotalWaves();
console.log("Retrieved total wave count...", count.toNumber());
} else {
console.log("Ethereum object does not exist!");
}
} catch (error) {
console.log(error)
}
}
return (
currentVisibility &&
<form onSubmit={(e) => handleSubmit(e)}>
<label>
Message:
<input type="text" value={currentFormText} onChange={(e) => handleChange(e.target.value)} />
</label>
<input type="submit" value="Submit" />
</form>
)
}
export default App;

Resources