Form validation error in ReactJS not firing first time - reactjs

My intention was to have a switch, and to validate the appropriate element using an onChange event. It looks like the onChange is sending the previous value of the input field, therefore my validateSearch function is not picking up an error straight away.
Here is an example. You will see that when the age is changed below 18, the onClick event lags behind. How can I prevent this?
https://codesandbox.io/s/vpgzk

Working sandbox
After you've read this code you may have some more questions. Feel free to ask them.
import React, { useState, useEffect } from "react";
const adultAge = 18
const childWarning = 'Under 18'
const emptyStr = ''
function App() {
const [readAge, writeAge] = useState("18");
const [readErrors, writeErrors] = useState({});
useEffect(() => {
if (readAge < adultAge) writeErrors({age: childWarning})
else writeErrors({age: emptyStr})
}, [readAge])
const tooYoung = readErrors.age !== emptyStr
return (
<div>
<form>
<input
type="number"
value={readAge}
onChange={(e) => writeAge(e.target.value)}
/>
<button type="submit" disabled={tooYoung}>Submit</button>
</form>
{tooYoung && <p style={{color: 'red'}}>You are not old enough</p>}
</div>
);
}
export default App;

Related

I have a problem I created a counter app, and then I added an input field.. But I want what I input in the field to reflect in the count section

I want what I input in the input field to reflect on the count and also be able to increase or decrease it(I mean the value inputted)
I created two states... The useState for count and input
If I understood correctly you want to update the counter via input and also with buttons as incremental.
Here is a quick React code below and you can find the sandbox link here. If you want to separate the link between the input and the counter just remove the line value={counter} from inside the input tag.
import React, { useState } from "react";
export default function App() {
const [counter, setCounter] = useState(777);
const updateNumber = (e) => {
e.preventDefault();
setCounter(Number(e.target.value));
};
const upNo = () => {
setCounter(counter + 1);
};
const downNo = () => {
setCounter(counter - 1);
};
return (
<div className="App">
<h1>Input your number</h1>
<button onClick={downNo}>-</button>
<input
value={counter}
name="mynumber"
id="mynumber"
type="number"
onChange={updateNumber}
/>
<button onClick={upNo}>+</button>
<br />
<h2>My Number: {counter}</h2>
</div>
);
}

Adding updated state to code editor only works once

I have an issue with my code below. When you click the add code button, it adds the code to the monaco code editor which is great. However, if you type some more code in the editor or erase whats currently there and then press the 'Add code' button, nothing is added. It's just blank.
Is there a way to whenever that 'Add code' button is clicked it clears everything in the editor and just adds the setAddCode state when the button is clicked?
And here is the code:
import { useState, useRef, useEffect } from "react";
import Editor from "#monaco-editor/react";
export default function IndexPage() {
const [input, setInput] = useState("");
const [addCode, setAddCode] = useState("# code goes here");
const editorRef = useRef(null);
function handleEditorDidMount(editor, monaco) {
setInput((editorRef.current = editor));
editorRef.current = editor;
}
return (
<div>
<div className="code-editor">
<Editor
width="100vh"
height="40vh"
theme="vs-dark"
fontSize="14"
defaultLanguage="python"
defaultValue=""
value={addCode}
onMount={handleEditorDidMount}
/>
</div>
<br />
<button onClick={() => setAddCode("print('Hello World!')")}>
Add code
</button>
</div>
);
}
The way the Editor component is set up, it will only change the value in the editor if you pass a different value prop. It's probably doing something similar to the following:
const Editor = ({ value }) => {
const [codeToDisplay, setCodeToDisplay] = useState(value);
useEffect(() => {
setCodeToDisplay(value);
}, [value]);
// etc
In your parent component, when you call setAddCode("print('Hello World!')") the first time, that'll result in the child component seeing a difference in how it was called - the value prop changed - so it'll know that there's something different to display, and update its own internal state appropriately. When you press the button again, the addCode value will stay the same - the Editor component doesn't see any difference, so it won't update.
To fix it, you can listen for changes from inside Editor by using its onchange prop to update the state in the parent component when the code inside the editor changes - that way, when you click the button later, the prop will be different, and the editor will know to update its internal state.
export default function IndexPage() {
const [input, setInput] = useState("");
const [codeValue, setCodeValue] = useState("# code goes here");
const editorRef = useRef(null);
function handleEditorDidMount(editor, monaco) {
setInput((editorRef.current = editor));
editorRef.current = editor;
}
return (
<div>
<div className="code-editor">
<Editor
width="100vh"
height="40vh"
theme="vs-dark"
fontSize="14"
defaultLanguage="python"
defaultValue=""
value={codeValue}
onChange={(newValue) => { setCodeValue(newValue); }}
onMount={handleEditorDidMount}
/>
</div>
<br />
<button onClick={() => setCodeValue("print('Hello World!')")}>
Add code
</button>
</div>
);
}

React- how to enable a button when TextField has value

So I'm trying to enable a button as soon as I enter a value in the TextField. The only way it is enabled is if i click outside the TextField after I put a value inside the Textfield. I know i'm missing something small but I still haven't found the correct way. I would appreciate your advice .
The code for the TextField and LoadingButton
the Window
I have included only the relevant part.
import { useState } from "react";
export default function Home() {
const [name, setName] = useState("");
const hanldeUserInput = (e) => {
setName(e.target.value);
};
return (
<Dialog>
<TextField onChange={hanldeUserInput} value={name} />
<LoadingButton disabled={name === ""}>Save</LoadingButton>
</Dialog>
);
}
You could keep track of the current value inside your textfield and store it inside the state.
const [txtFieldValue, setTxtFieldValue] = useState<string>('')
and write a function which is triggered on the change event in your textfield:
function handleTxtFieldChange(event) {
if (event.target.id === 'myTextFieldId') {
setTxtFieldValue(event.target.value)
}
}
And then you can adjust your textfield:
<TextField
id={'myTextFieldId'}
// ... all your other stuff
onChange={(event) => {
handleTxtFieldChange(event)
}}
/>
and you can then use the set txtFieldValue to render the button like:
{txtFieldValue != '' ? <Button /> : <></>}
or if you just want to disable it you can just use the
txtFieldValue != ''
as a boolean.

Persistent way for getting an Input Value using Hooks

I'm a beginner at React. I'm trying to build a component that recovers the text of an input and later on inserts it on the HTML.
import React, { useState } from 'react';
function InputGetter(){
const [text, setText] = useState("")
let typed = ""
return(
<div>
<input type='text' onChange = {(e)=> typed = e.target.value}></input>
<button onClick={() => setText(typed)}>Set Text</button>
Text typed was "{text}"
</div>
)
}
export default InputGetter
The code above works for clicks when there's a change triggered. However, when I try to double click it, even when there's content on the input, text somehow is set to "". I'm not sure why it happens. How can I make the textvariable content persistent?
You have closure on text value within the onClick callback, to persist value between renders, you can use useRef hook, see Is there something like instance variables?.
function InputGetter() {
const [text, setText] = useState('');
const inputRef = useRef('');
return (
<div>
<input type="text" ref={inputRef}></input>
<button onClick={() => setText(inputRef.current.value)}>Set Text</button>
Text typed was "{text}"
</div>
);
}

Custom react hook to set input form not working

I've tried creating a custom hook, following the examples an article about handling forms in react using hooks. I should also add I'm very new to react.
This is the content of hooks/useInput.js:
import { useState } from "react";
function useInput(initialValue) {
const [value, setValue] = useState(initialValue);
function handleChange(event) {
console.log(event.target.name);
console.log(event.target.value);
setValue(event.target.value);
}
return [value, handleChange];
}
export default useInput;
In a component I have the following:
import useInput from "hooks/useInput";
export default function Address(props) {
const [fullName, setFullName] = useInput("");
return (
<FormControl fullWidth>
<CustomInput
required
labelText="Full name"
id="fullName"
formControlProps={{
fullWidth: true
}}
value={fullName}
onChange={setFullName}
/>
</FormControl>
);
}
When I try to input some text (or even if I try to change the default state), nothing happens.
Any breakpoint that I set in useInput.js are not hit and no logging appears in the console.
Where am I going wrong?
If you want to see your current input value with a button click you can see like this. I didn't even change your userInput.js file. I can see the updated value by doing this and console as well.
export default function Address(props) {
const [fullName, setFullName] = useInput("");
return (
<>
<input
placeholder="Name"
value={fullName}
onChange={setFullName}
/>
<button onClick={() => {
console.log(fullName);
}}>Submit</button>
</>
);
}
Since I don't know about your CustomInput, I have written this with default input and button. Please check your CustomInput correctly. Because default input is working.

Resources