Im trying to console.log the input value inside Input but every time i type something the page reloads. Console show no errors.
const [enteredText, setEnteredText] = useState("");
const textHandler = (event) => {
setEnteredText(event.target.value);
};
const submitHandler = (event) => {
event.preventDefault();
const textData = {
text: enteredText,
};
console.log(textData);
};
return (
<Post onSubmit={submitHandler}>
<TopPost>
<ProfilePicture></ProfilePicture>
<Input
placeholder="What's happening?"
required
onChange={textHandler}
/>
</TopPost>
<BottomPost>
<Button type="submit">Post</Button>
</BottomPost>
</Post>
Related
I designed a flash card and I want to change the text of the card when I click on the button, but I do not know how to send the form information to the App component to update the state.
App component
function App() {
const [flashCard, setFlashCard] = useState({
word: "test",
persianEquivalent: "test",
});
const setFlashCardHandler = (e) => {
setFlashCard({ flashCard: e });
};
return (
<div className="container">
<Form setFlashCard={setFlashCardHandler} />
<FlashCard flashCard={flashCard} />
</div>
);
}
export default App;
Form component:
function Form({ setFlashCard }) {
const [valueEn, setValueEn] = useState();
const [valuePer, setValuePer] = useState();
const setValueHandlerEn = (e) => {
setValueEn(e.target.value);
};
const setValueHandlerPer = (e) => {
setValuePer(e.target.value);
};
const setFlashCardHandler = (e) => {
e.preventDefault();
setFlashCard((e)=>{valueEn=e.target[0].value});
};
return (
<form onSubmit={setFlashCardHandler}>
<input
id="word-input"
placeholder="world"
value={valueEn}
onChange={setValueHandlerEn}
/>
<input
id="persian-equivalent-input"
placeholder="Equivalent"
value={valuePer}
onChange={setValueHandlerPer}
/>
<button id="submit-btn">send</button>
</form>
);
}
export default Form;
There is an issue with how you set values.
Pass setFlashCard as the prop to Form
<Form setFlashCard={setFlashCard} />
In Form change the setFlashCardHandler as below.
const setFlashCardHandler = (e) => {
e.preventDefault();
setFlashCard({ word: valueEn, persianEquivalent: valuePer });
};
Set empty string ("") as default state to avoid sending undefined.
const [valueEn, setValueEn] = useState("");
const [valuePer, setValuePer] = useState("");
Please add new updateFlashCard props to to component.
Like:
<Form updateFlashCard={(e) => setFlashCard(e)}/>
And change value in updateFlashCard state from form component
Like:
function Form({ updateFlashCard }) {
const [valueEn, setValueEn] = useState();
const [valuePer, setValuePer] = useState();
const setValueHandlerEn = (e) => {
setValueEn(e.target.value);
};
const setValueHandlerPer = (e) => {
setValuePer(e.target.value);
};
const setFlashCardHandler = (e) => {
e.preventDefault();
updateFlashCard(e.target[0].value) // update from here
};
return (
<form onSubmit={setFlashCardHandler}>
<input
id="word-input"
placeholder="world"
value={valueEn}
onChange={setValueHandlerEn}
/>
<input
id="persian-equivalent-input"
placeholder="Equivalent"
value={valuePer}
onChange={setValueHandlerPer}
/>
<button id="submit-btn">send</button>
</form>
);
}
export default Form;
My goal after clicking the register button is:
Make input fields blank
Do not show error tooltips
Here is the link on CodeSandbox
I've already tried using event.target.reset(); however the tooltips are still appearing on the screen.
export default function App() {
const [showSucessAlert, setshowSucessAlert] = useState(false);
const [validated, setValidated] = useState(false);
const [transitionAlert, setTransitionAlert] = useState(false);
const handleSubmit = (event) => {
const form = event.currentTarget;
event.preventDefault();
if (form.checkValidity() === false) {
event.stopPropagation();
} else {
handleClickTransitionAlert();
setshowSucessAlert(true);
}
setValidated(true);
};
const handleClickTransitionAlert = () => {
setTransitionAlert(true);
setTimeout(() => {
setTransitionAlert(false);
}, 1700);
};
return (
<Form noValidate validated={validated} onSubmit={handleSubmit}>
<Form.Group className="position-relative" controlId="validationPassword">
<Form.Label>Password</Form.Label>
<InputGroup hasValidation id="validationPassword" />
<Form.Control
type="password"
aria-describedby="validationPassword"
required
/>
<Form.Control.Feedback tooltip type="invalid">
Please enter your Password.
</Form.Control.Feedback>
</Form.Group>
<Alert
className={`mt-1 p-1 position-fixed ${
transitionAlert ? "alert-shown" : "alert-hidden"
}`}
show={showSucessAlert}
variant="success"
>
Registered user!
</Alert>
<Button className="mt-5" variant="primary" type="submit">
Register
</Button>
</Form>
);
}
Here is the link on CodeSandbox
Every help is welcome!
I don't commonly use uncontrolled components, but I think you could solve this by adding setValidated(false) and event.target.reset() to the handleClickTransitionAlert, like this:
const handleClickTransitionAlert = (event) => {
setTransitionAlert(true);
setTimeout(() => {
setTransitionAlert(false);
setValidated(false)
event.target.reset()
}, 1700);
};
Try reseting the validated attribute on Bootsrap Form.
it should look something like this (this is pseudo-code):
import React, { useRef, useState } from 'react';
const FormComponent = () => {
const [validated, setValidated] = useState(false);
const formRef = useRef(null);
const handleReset = () => {
formRef.current.reset();
setValidated(false);
};
const handleSubmit = () => {
// Do stuff here
// On success or error:
setValidated(true);
handleReset();
}
return(
<Form ref={formRef} validated={validated} onSubmit={handleSubmit}>
// your form inputs
</Form>
);
export default FormComponent;
}
I created a hook to handle a tooltip for different fields(useToolTip). This hook needs to create a piece of state with the current tip that is open in a formField that should be a string. Then return a callback if a new tip has been open which sets the current tip to be equal to the passed argument based on the fieldName.
This way a form will call thisuseToolTip hook and pass the return state and callback down to each form field. the form field will pass its fieldName property and the hook return to the tooltip component.
I also have a button (ToolTipButton) that needs to call the new tip callback function onclick with its fieldName property as a parameter.
The text box for this tooltip(ToolTipTextBox) will check to see if the current tip property (state from hook) is equal to its fieldName property if so then the tip will be render.
How can I accomplish this?
Here are all my components:
function useToolTip() {
const {
currentTip
} = useState(formField);
const showTooltip = useCallback(
(_text: string) => {
setShow(true);
setText(_text);
},
[setShow, setText]
);
const hideTooltip = () => {
setShow(false);
};
return {
currentTip
};
}
export default useToolTip;
Form:
const NewModelForm: FunctionComponent<NewModelFormProps> = (props) => {
const { chooseFolder, onSubmit, chooseFile } = props;
const history = useHistory();
return (
<Form
onSubmit={(data) => {
// console.log(data);
onSubmit(data);
}}
id="new_model_form"
>
<FormField
label="Simulation Name"
name="name"
placeholder="Enter a name for the simulation."
tip="Enter a name to save your simulation as."
required
defaultValue="Simulation 1"
/>
<OutputPathFieldset onClick={chooseFolder} defaultPath="/" />
<FormField
label="End Time (years)"
type="number"
name="end_time"
defaultValue={10}
step={1}
tip="Enter the number of years to run the simulation."
/>
<FormField
label="Time Step (years)"
type="number"
name="time_step"
defaultValue={0.5}
tip="Enter the number of years for a time step"
step={0.1}
/>
<AnalysisTypeFieldset />
<Dropdown
name="logging"
label="Logging"
choices={{
bug: 'Debug',
info: 'Info',
warn: 'Warning',
err: 'Error',
}}
tip="Select a logging type"
/>
<ReservoirTypeFieldset
chooseFile={chooseFile}
chooseFolder={chooseFolder}
/>
<FormControls
onCancel={() => history.push('/')}
formID="new_model_form"
/>
</Form>
);
};
NewModelForm.defaultProps = {};
Button:
const ToolTipButton: FunctionComponent<ToolTipButtonProps> = (props) => {
const { onClick } = props;
return (
<button type="button" className="form__tooltip" onClick={onClick}>
<BsQuestion />
</button>
);
};
ToolTipButton.defaultProps = {};
export type ToolTipButtonProps = {
onClick: () => void;
};
export default ToolTipButton;
Text box:
import React from 'react';
const ToolTipTextBox = (props) => {
const {} = props
return (
<div> Tool tip box </div>
)
}
export default ToolTipTextBox
Thank you!!!!!!!
I created a simple to do list wherein the add and delete works. My problem is, after submitting a todo, the input box won't clear.
This is my app.js
const App = () => {
const [toDoList, setToDoList] = useState([]);
const [toDo, setToDo] = useState("");
const handleToDo = (event) => {
const { value } = event.target;
setToDo(value);
};
const submit = () => {
//const list = toDoList;
const newItem = {
id: 1 + Math.random(),
value: toDo,
};
if (newItem.value && !toDoList.includes(newItem.value)) {
toDoList.push(newItem);
setToDoList([...toDoList]);
}
};
return (
<div className="container">
Add an Item
<br />
<input
type="text"
placeholder="Type item here..."
onChange={handleToDo}
/>
<button className="add-btn btn-floating" onClick={submit}>
<i class="material-icons"> + </i>
</button>
<br />
<ul>
...display of todos here
</ul>
</div>
);
//}
};
export default App;
I'm confused as to where I should insert the useState so that the input would be reset.
The value of the input box must also be governed by the state. So the input should be like:
<input
value={toDo}
type="text"
placeholder="Type item here..."
onChange={handleToDo}
/>
Once You click on submit, reset the toDo to empty
const submit = () => {
//const list = toDoList;
const newItem = {
id: 1 + Math.random(),
value: toDo,
};
if (newItem.value && !toDoList.includes(newItem.value)) {
toDoList.push(newItem);
setToDoList([...toDoList]);
}
setToDo("");
};
Your input seems to be half-controlled. You should also give the input a value property as such:
<input
type="text"
placeholder="Type item here..."
onChange={handleToDo}
value={toDo}
/>
And now you can clear out the input when a task is submitted:
const submit = () => {
//rest of the code here...
setToDo('') //this'll clear out the value of your input
};
You can add a value to input element. And after submit, set it to an empty string. So:
const App = () => {
const [toDoList, setToDoList] = useState([]);
const [toDo, setToDo] = useState("");
const handleToDo = (event) => {
const { value } = event.target;
setToDo(value);
};
const submit = () => {
//const list = toDoList;
const newItem = {
id: 1 + Math.random(),
value: toDo,
};
if (newItem.value && !toDoList.includes(newItem.value)) {
toDoList.push(newItem);
setToDoList([...toDoList]);
setToDo("");
}
};
return (
<div className="container">
Add an Item
<br />
<input
type="text"
value={toDo}
placeholder="Type item here..."
onChange={handleToDo}
/>
<button className="add-btn btn-floating" onClick={submit}>
<i class="material-icons"> + </i>
</button>
<br />
<ul>
{toDoList.map((todoLi) => (
<li>{todoLi}</li>
))}
</ul>
</div>
);
//}
};
export default App;
You just have to pass empty string in setToDo, after all the code in your submit function setToDo("")
I have a form with an email that creates an account on the backend
and the user can change the email in this step. This code do this by putting the function in onBlur, but if I change the email in the input and don't leave the field, onBlur doesn't happen. I can click submit direct, sending my old email for account creation.
This is the code:
const SendForm = ({ submit }) => {
const onLabelSubmit = () => async (event, newValue, name) => {
handleLabelSubmit(newValue, name);
};
const submitForm = () => {
// validations
submit();
};
const handleSubmitAccount = (e) => {
e.preventDefault();
dispatch(submitAccount(field.name, field.email))
.then(() => {
submitForm();
});
};
return (
<form onSubmit={handleSubmitAccount}>
<Field
id="email"
name="email"
label="label"
onBlur={onLabelSubmit(label.email)}
/>
<Button type="submit">
Submit Form
</Button>
</form>
);
};
Is there any way to do what onBlur does, but when I click the submit button?
I need improving the experience and avoiding mistakes.
Thanks!
Add state to the component with useState.
Instead of onBlur use onChange and add value property to your input field, it will fire on every user input so you will always have the latest given email & username.
const SendForm = ({ submit }) => {
const [fields, setFields] = useState({ name: '', email: '' })
const onFieldChange = () => async (newValue, name) => {
setFields({ ...fields, [name]: newValue });
};
const submitForm = () => {
// validations
submit();
};
const handleSubmitAccount = (e) => {
e.preventDefault();
dispatch(submitAccount(field.name, field.email))
.then(() => {
submitForm();
});
};
return (
<form onSubmit={handleSubmitAccount}>
<Field
id="email"
name="email"
label="label"
value={fields.email}
onChange={onFieldChange(label.email)}
/>
<Button type="submit">
Submit Form
</Button>
</form>
);
};