How to reset input field from useRef in React? - javascript

I have a text input. If I click on a specific button in the page, I want to reset the value of the input. Here is my code:
const inputRef = useRef()
const handleClick= () => {
inputRef.current.value.reset();
return "hello world"
}
return (
<>
<input type="text" ref={inputRef}/>
<button onClick={()=> handleClick}>delete all</button>
</>
)
It doesn't work. How to fix this?

reset is available on form element.
You can wrap your input with a form, and trigger reset on it.
const {useRef} = React;
const App = () => {
const formRef = useRef();
const handleClick = () => {
formRef.current.reset();
};
return (
<form ref={formRef}>
<input type="text" />
<input type="password" />
<input type="checkbox" />
<textarea></textarea>
<button onClick={handleClick} type="button">
clear form
</button>
</form>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>

You can clear the value in the input field like below.
const handleClick= () => {
inputRef.current.value = "";
return "hello world"
}
and change onClick call in the button like below
onClick={handleClick}
//or
onClick={()=> handleClick()}
If you want complete reset of a form having multiple inputs, you can follow the below approach.
In below example, form will reset after submit
const formRef = useRef();
const handleClick = () => {
formRef.current.reset();
}
render() {
return (
<form ref={formRef}>
<input />
<input />
...
<input />
</form>
);
}
if you don't want to use Ref
const handleSubmit = e => {
e.preventDefault();
e.target.reset();
}
<form onSubmit={handleSubmit}>
...
</form>

You can clear the text input field by setting its value to an empty string. You can do that like this inputref.current.value = "" if you want to use uncontrolled inputs.
However, if you want to use controlled inputs you can create a state variable to track the value of the input field. For example,
const SomeComponent = () => {
const [text, setText] = useState('')
return (
<>
<input type="text" value={text} onChange={(e) => setText(e.target.value)} />
<button onClick={() => setText('')}>delete all</button>
</>
);
};
Here is a codesandbox with both implementation.

You have two problems, one you are passing a function that calls a function into your onClick handler -- which isn't needed. If you define the function before your render, you do not need to pass an anonymous function to the onClick handler.
// Before
<button onClick={()=> handleClick}>delete all</button>
// After
<button onClick={handleClick}>delete all</button>
The other problem is that your handleClick function calls reset, which is not a function on an input. To reset the value of the referenced input, you can set it to an empty string (or whatever you want the "default" value to be).
const handleClick = e => {
inputRef.current.value = "";
return "hello world";
};

rest value in input
import { useRef } from 'react'
const Test = () => {
const testRef = useRef(null)
return (
<div>
<input type="text" ref={testRef} />
<button onClick={() => inputSearch.current.value = ''}>×</button>
</div>
)
}
export default Test

Related

How to pass a value in a form OnPost method React

const afterSubmission = (e, message) => {
e.preventDefault()
console.log(message);
if (message === "") return
displayMessage(message)
messageInput.value=""
}
<div id="message-container"></div>
<form onSubmit = {afterSubmission}>
<label for="message-input">Message</label>
<input type="text" id="message-input" />
<button type="submit" id="send-button">Send</button>
</form>
I have these two pieces of code, my question is how can I pass the value from the input tag in the form to the afterSubmission method?
Assuming this is the same component, an easy solution would be to use state.
Your code snippets aren't very useful, just as an FYI for future questions, but here's an example of me tracking form state.
import { useState } from "react";
export default function App() {
const [message, setMessage] = useState("test");
const handleChange = (e) => {
setMessage((old) => e.target.value);
};
const afterSubmission = (e) => {
e.preventDefault();
console.log(message);
};
return (
<div className="App">
<form onSubmit={afterSubmission}>
<input
type="text"
id="message-input"
value={message}
onChange={handleChange}
/>
<button
type="submit"
id="send-button"
>
Send
</button>
</form>
</div>
);
}
As you can see, this tracks your message in the component's state which makes it accessible in the afterSubmission function.

How to create dynamic (conditional) placeholder in React.js

So I have a submit form where the user needs to create a task by typing in a task name. I want it to be empty at the beginning and have a placeholder of "you must enter a task" when the user click add without entering anything. Now I can achieve it to display the placeholder but it's either always there or I encounter unreachable code. I know how to clean the submission & return to the add function, just need to be able to display the placeholder conditionally. Here's what my code looks like atm:
import { useState } from "react";
export default function Todos() {
const [todos, setTodos] = useState([{ text: "hey" }]);
const [todoText, setTodoText] = useState("");
const [isEmpty, setEmpty] = useState("false");
const addTodo = (e) => {
e.preventDefault();
if (todoText){
setTodos([...todos, { text: todoText }]);
setTodoText("");
} else {
setEmpty(true)
setTodoText("");
return
}
}
return (
<div>
{todos.map((todo, index) => (
<div key={index}>
<input type="checkbox" />
<label>{todo.text}</label>
</div>
))}
<br />
<form onSubmit={addTodo}>
<input
value={todoText}
onChange={(e) => setTodoText(e.target.value)}
type="text"
></input>
<button type="submit">Add</button>
{isEmpty &&<span style={{ color: "red" }}>Enter a task</span>}
</form>
</div>
);
}
I could change your code with the following:
You need to initialize isEmpty by false instead of string "false".
And you can use this flag on showing placeholder texts.
Note that I renamed isEmpty by showError.
import { useState } from "react";
export default function Todos() {
const [todos, setTodos] = useState([{text: "hey"}]);
const [todoText, setTodoText] = useState("");
const [showError, setShowError] = useState(false);
// #ts-ignore
const addTodo = (e) => {
e.preventDefault();
if (todoText) {
setTodos([...todos, {text: todoText}]);
setTodoText("");
setShowError(false);
} else {
setTodoText("");
setShowError(true);
return
}
}
return (
<div>
{todos.map((todo, index) => (
<div key={index}>
<input type="checkbox"/>
<label>{todo.text}</label>
</div>
))}
<br/>
<form onSubmit={addTodo}>
<input
value={todoText}
onChange={(e) => setTodoText(e.target.value)}
type="text"
></input>
<button type="submit">Add</button>
{(showError && !todoText) && <span style={{color: "red"}}>Enter a task</span>}
</form>
</div>
);
}

Creating div in function (React)

I have an exercise where I have to make an input and a button. When I click the button, there has to be created a div/span below, which prints the text which is in input. If I change the text in input, it has to be refreshed in that div/span only when I click the button again. I tried to do it with makeDiv function, but it doesn't do anything. I made console.log(event.target.value) and it handles the text which is in input, but nothing happens then.
My code:
import {useState} from "react"
function About() {
const [initialValue,setInitialValue] = useState('')
const handleValueChange = (event) => {
console.log(event.target.value)
setInitialValue(event.target.value)
}
const makeDiv = () => {
return (<div>Value: {initialValue}</div>)
}
return(
<div>
<button onClick={makeDiv}>click me</button>
<div><input type="text" onChange={handleValueChange} /></div>
</div>
)
}
export default About
edit:
What if I wanted to make an exercise very similar to that, but now, I have to add <li>text in input</li> to <ul> each time I click the button. So when I click the button, I add one li to the list, I tried like this, but it doesn't compile:
import {useState} from "react"
function About() {
const [initialValueLastExercise, setInitialValueLastExercise] = useState([])
const [ValueLE, setValueLE] = useState([])
const handleValueChangeLE = (event) => {
console.log(event.target.value)
setInitialValueLastExercise([...initialValueLastExercise, event.target.value])
}
const showListWithText = () => {
setShouldDisplayText(true)
setValueLE(initialValueLastExercise)
}
return(
<div>
<button onClick={showListWithText}>click me to refresh the list</button>
<div><input type="text" onChange={handleValueChangeLE} /></div>
{shouldDisplayText && <div><ul>
{
for (let i =0; i<initialValueLastExercise.length; i++) {
<li>{initialValueLastExercise[i]}</li>
}
}</div></ul>}
</div>
)
}
export default About
This will refresh the value of the div on button click only as you have mentioned in the question.
import {useState} from "react"
function App() {
const [initialValue,setInitialValue] = useState('')
const [displayText, setDisplayText] = useState(false)
const [Value,setValue] = useState('')
const handleValueChange = (event) => {
setInitialValue(event.target.value)
}
const showText = () => {setDisplayText(true)
setValue(initialValue)};
return(
<div>
<button onClick={showText}>click me</button>
<div><input type="text" onChange={handleValueChange} /></div>
{displayText && <div>Value: {Value}</div>}
</div>
)
}
export default App
Solution for the Edited Question.
import {useState} from "react"
function App() {
const [initialValue,setInitialValue] = useState('')
const [displayText, setDisplayText] = useState(false)
const [Value,setValue] = useState([])
const handleValueChange = (event) => {
setInitialValue(event.target.value)
}
const showText = () => {setDisplayText(true)
setValue([...Value,initialValue])};
return(
<div>
<button onClick={showText}>click me</button>
<div><input type="text" onChange={handleValueChange} /></div>
<ul>{displayText && Value.length > 0 &&
Value.map((i) => {
return <li>Value: {i}</li>
})}</ul>
</div>
)
}
export default App
One way to do it is to create another state variable which indicates whether the div you're trying to make should be displayed and then render it conditionally. Something like
import {useState} from "react"
function About() {
const [initialValue,setInitialValue] = useState('')
const [shouldDisplayText, setShouldDisplayText] = useState(false)
const handleValueChange = (event) => {
console.log(event.target.value)
setInitialValue(event.target.value)
}
const showDivWithText = () => setShouldDisplayText(true);
return(
<div>
<button onClick={showDivWithText}>click me</button>
<div><input type="text" onChange={handleValueChange} /></div>
{shouldDisplayText && <div>Value: {initialValue}</div>}
</div>
)
}
export default About
Your approach is fundamentally wrong.
You should:
Store all the data about the component in the state
Render the output based on the state
So:
You need two state variables:
currentInputValue (because you need to store the value to display and edit in input)
selectedValue (because you need to store the value to be displayed in the div)
When onChange fires, update currentInputValue with the value of the input.
When onClick fires, update selectedValue with the current value of currentInputValue
When you return your data, include something like:
{selectedValue && <div>{selectedValue}</div>}
… to output a div containing the selected value only if there is a truthy value (the default empty string isn't truthy so the div won't be output then)
1st possibility - close to your code source
Don't forget to bind initialValue to the input and to add makeDiv content to the JSX :
return (
<div>
<button onClick={makeDiv}>click me</button>
<input type="text" onChange={handleValueChange} value={initialValue} />
{makeDiv}
</div>
)
2nd possibility - with another approach
return (
<div>
<button onClick={makeDiv}>click me</button>
<input type="text" onChange={handleValueChange} value={initialValue} />
{initialValue && <div>{initialValue}</div>}
</div>
)

Update Button state onClick React

I have two buttons on a page and based on a state in that component, a particular button should be displayed, I have tried for hours, still not working
Here is my code
const App = () =>{
const [edit,setEdit] = useState(false)
const updateUser =() =>{
//update action
setEdit(false)
}
return(
<div>
<form>
<input type="text"/>
<input type="text"/>
{edit ? (<button onClick={()=>updateUser()}>Save</button>) : (<button onClick={()=>{setEdit(true)}}>Edit</button>)}
</form>
</div>
)
}
export default App;
when the page loads the button shows Edit, but after clicking, i expect it to change to save since edit is now true, but it still remains same
you have a side effect in this situation caused by edit so you should make use of good old pal useEffect also those prevenDefaults will prevent your form from refreshing and are necessary. I made a livedemo at codeSandbox and here is the code itself:
import React, { useState, useEffect } from "react";
const App = () => {
const [edit, setEdit] = useState(false);
const updateUser = (e) => {
e.preventDefault();
//update action
setEdit(false);
};
const editUser = (e) => {
e.preventDefault();
//stuffs you wanna do for editing
setEdit(true);
};
useEffect(() => {}, [edit]);
return (
<div>
<form onSubmit={(e) => updateUser(e)}>
<input type="text" />
<input type="text" />
{edit ? (
<button type="submit">Save</button>
) : (
<button onClick={(e) => editUser(e)}>Edit</button>
)}
</form>
</div>
);
};
export default App;
P.S: Although it works, I don't approve of the approach
You can try this approach also, Here I used e.preventDefault on the event when submitting the form to prevent a browser reload/refresh.
const App = () =>{
const [edit,setEdit] = useState(false)
const updateUser =(e) =>{
//update action
e.preventDefault();
setEdit(!edit);
}
return(
<div>
<form>
<input type="text"/>
<input type="text"/>
{edit ? (<button onClick={updateUser}>Save</button>) :
(<button onClick={updateUser}>Edit</button>)}
</form>
</div>
)
}
export default App;
Not need to using useEffect just check if edit is true or not !
EDIT : I made it this way so u can see what happend and i think u should learn more about react and hooks , i prefer watching youtube!
const App = () => {
const [edit, setEdit] = React.useState(true);
const clickHandler =(e)=>{
e.preventDefault();
if(!edit){
// update user information here not need to make
// different function and state or somthing else.
console.log("updateUser")
}
setEdit(prev=>!prev);
}
return(
<div>
<form>
<input type="text"/>
<input type="text"/>
<button onClick={clickHandler} disabled={!edit}>Edit</button>
<button onClick={clickHandler} disabled={edit}>Save</button>
</form>
</div>
)
}
ReactDOM.render(<App />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Issue
As I see it, your issue is that the buttons don't have a type specified to them, so they actually inherit an initial value of type="submit" and this causes your form to take the default submit action and reload the page. You likely aren't seeing this reload as it may be occurring very quickly.
type
The default behavior of the button. Possible values are:
submit: The button submits the form data to the server. This is the default if the attribute is not specified for buttons associated
with a <form>, or if the attribute is an empty or invalid value.
reset: The button resets all the controls to their initial values, like <input type="reset">. (This behavior tends to annoy users.)
button: The button has no default behavior, and does nothing when pressed by default. It can have client-side scripts listen to the
element's events, which are triggered when the events occur.
Solution
Provide/specify the button types to not be "submit and valid, i.e. use type="button".
const App = () => {
const [edit, setEdit] = React.useState(false);
const updateUser = () => {
//update action
setEdit(false);
};
return (
<div>
<form>
<input type="text" />
<input type="text" />
{edit ? (
<button type="button" onClick={updateUser}>
Save
</button>
) : (
<button
type="button"
onClick={() => {
setEdit(true);
}}
>
Edit
</button>
)}
</form>
</div>
);
};
Here is an example that also, IMO, make the code a bit more DRY.
const App = () => {
const [edit, setEdit] = React.useState(false);
const updateUser = () => {
//update action
setEdit(false);
};
return (
<div>
<form>
<input type="text" />
<input type="text" />
<button
type="button"
onClick={() => {
edit ? updateUser() : setEdit(true);
}}
>
{edit ? "Save" : "Edit"}
</button>
</form>
</div>
);
};
Demo

Clear an input field with Reactjs?

I am using a variable below.
var newInput = {
title: this.inputTitle.value,
entry: this.inputEntry.value
};
This is used by my input fields.
<input type="text" id="inputname" className="form-control" ref={el => this.inputTitle = el} />
<textarea id="inputage" ref={el => this.inputEntry = el} className="form-control" />
<button className="btn btn-info" onClick={this.sendthru}>Add</button>
Once I activate {this.sendthru} I want to clear my input fields. However, I am uncertain how to do so.
Also, as shown in this example, it was pointed out to me that I should use the ref property for input values. What I am unclear of is what exactly does it mean to have {el => this.inputEntry = el}. What is the significance of el in this situation?
Let me assume that you have done the 'this' binding of 'sendThru' function.
The below functions clears the input fields when the method is triggered.
sendThru() {
this.inputTitle.value = "";
this.inputEntry.value = "";
}
Refs can be written as inline function expression:
ref={el => this.inputTitle = el}
where el refers to the component.
When refs are written like above, React sees a different function object each time so on every update, ref will be called with null immediately before it's called with the component instance.
Read more about it here.
Declare value attribute for input tag (i.e value= {this.state.name}) and if you want to clear this input value you have to use this.setState({name : ''})
PFB working code for your reference :
<script type="text/babel">
var StateComponent = React.createClass({
resetName : function(event){
this.setState({
name : ''
});
},
render : function(){
return (
<div>
<input type="text" value= {this.state.name}/>
<button onClick={this.resetName}>Reset</button>
</div>
)
}
});
ReactDOM.render(<StateComponent/>, document.getElementById('app'));
</script>
I'm not really sure of the syntax {el => this.inputEntry = el}, but when clearing an input field you assign a ref like you mentioned.
<input type="text" ref="someName" />
Then in the onClick function after you've finished using the input value, just use...
this.refs.someName.value = '';
Edit
Actually the {el => this.inputEntry = el} is the same as this I believe. Maybe someone can correct me. The value for el must be getting passed in from somewhere, to act as the reference.
function (el) {
this.inputEntry = el;
}
I have a similar solution to #Satheesh using React hooks:
State initialization:
const [enteredText, setEnteredText] = useState('');
Input tag:
<input type="text" value={enteredText} (event handler, classNames, etc.) />
Inside the event handler function, after updating the object with data from input form, call:
setEnteredText('');
Note: This is described as 'two-way binding'
You can use input type="reset"
<form action="/action_page.php">
text: <input type="text" name="email" /><br />
<input type="reset" defaultValue="Reset" />
</form>
Now you can use the useRef hook to get some magic if you do not want to use the useState hook:
function MyComponent() {
const inputRef = useRef(null);
const onButtonClick = () => {
// #ts-ignore (us this comment if typescript raises an error)
inputRef.current.value = "";
};
return (
<>
<input ref={inputRef} type="text" />
<button onClick={onButtonClick}>Clear input</button>
</>
);
}
As I mentioned, if you are using useState that is the best way. I wanted to show you also this special approach.
Also after React v 16.8+ you have an ability to use hooks
import React, {useState} from 'react';
const ControlledInputs = () => {
const [firstName, setFirstName] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
if (firstName) {
console.log('firstName :>> ', firstName);
}
};
return (
<>
<form onSubmit={handleSubmit}>
<label htmlFor="firstName">Name: </label>
<input
type="text"
id="firstName"
name="firstName"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<button type="submit">add person</button>
</form>
</>
);
};
You can use useState:
import React, { useState } from 'react';
const [inputTitle, setInputTitle] = useState('');
then add value to your input component:
render() {
<input type="text" onChange={(e) => setInputTitle(e.target.value)}
value={inputTitle} />
<button onClick={handleSubmit} type="submit">Submit</button>
}
On your submit handler function:
setInputTitle('');
document.querySelector('input').defaultValue = '';
On the event of onClick
this.state={
title:''
}
sendthru=()=>{
document.getElementByid('inputname').value = '';
this.setState({
title:''
})
}
<input type="text" id="inputname" className="form-control" ref={el => this.inputTitle = el} />
<button className="btn btn-info" onClick={this.sendthru}>Add</button>
I used the defaultValue property, useRef, and onClick to achieve this.
let ref = useRef()
and then inside the return:
<input type="text" defaultValue="bacon" ref={ref} onClick={() => ref.current.value = ""} />
also if you want to use onChange for the input it wouldn't require any more configuration and you can just use it. If you want to have a dynamic defaultValue then you absolutely can, with useState.
A simple way to reset the input in React is by implementing the onBlur inside the input.
onBlur={cleanSearch}
ej:
const [search, setSearch] = useState('')
const handleSearch = ({target}) =>{
setSearch(target.value)
}
const cleanSearch = () =>setSearch('')
<input
placeholder="Search…"
inputProps={{ 'aria-label': 'search' }}
value={search}
onChange={handleSearch}
onBlur={cleanSearch}
/>
The way I cleared my form input values was to add an id to my form tag.
Then when I handleSubmit I call this.clearForm()
In the clearForm function I then use document.getElementById("myForm").reset();
import React, {Component } from 'react';
import './App.css';
import Button from './components/Button';
import Input from './components/Input';
class App extends Component {
state = {
item: "",
list: []
}
componentDidMount() {
this.clearForm();
}
handleFormSubmit = event => {
this.clearForm()
event.preventDefault()
const item = this.state.item
this.setState ({
list: [...this.state.list, item],
})
}
handleInputChange = event => {
this.setState ({
item: event.target.value
})
}
clearForm = () => {
document.getElementById("myForm").reset();
this.setState({
item: ""
})
}
render() {
return (
<form id="myForm">
<Input
name="textinfo"
onChange={this.handleInputChange}
value={this.state.item}
/>
<Button
onClick={this.handleFormSubmit}
> </Button>
</form>
);
}
}
export default App;

Categories