Update Button state onClick React - javascript

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

Related

Prevent form from being refreshing when submitted in Reactjs

Hi I have a Reactjs component in this component .I have a form inside the form i have a search field..when the user hit enter my component reloads.I want to use |prevent defaultso that mycomponentnot reloads when user hitsenter key.How to use in my code`
import React, { useState } from "react";
import data from "./info.json";
function App() {
const [searchTerm, setSearch] = useState(null);
return (
<div>
<form>
<input
type="text"
id=""
placeholder="Search"
onChange={(e) => setSearch(e.target.value)}
/>
</form>
{data
.filter((data) => {
if (searchTerm == null) {
return data;
} else if (
data.name.toLowerCase().includes(searchTerm.toLowerCase())
) {
return data;
}
})
.map((data) => (
<li>{data.name}</li>
))}
</div>
);
}
export default App;
ReactJS supports the onSubmit event by emitting synthetic events for native HTML elements.
For a <form> element, you can use the submit event to prevent the default behavior by using event.preventdefault().
You can do it in two easy steps:
Define an event handler for your form
Use the event handler to prevent form submission
import React, { useState } from "react";
import data from "./info.json";
function App() {
const [searchTerm, setSearch] = useState(null);
const fnHandleSubmit = event => {
event.preventDefault();
}
return (
<div>
<form onSubmit={fnHandleSubmit}>
<input
type="text"
id=""
placeholder="Search"
onChange={(e) => setSearch(e.target.value)}
/>
</form>
{data
.filter((data) => {
if (searchTerm == null) {
return data;
} else if (
data.name.toLowerCase().includes(searchTerm.toLowerCase())
) {
return data;
}
})
.map((data) => (
<li>{data.name}</li>
))}
</div>
);
}
export default App;
Add an onSubmit event handler on the form ,
<form onSubmit={handleOnsubmit}> </form>
in your handleOnsubmit function perfrom event.preventDefault()
function handleOnsubmit(event) {
event.preventDefault();
// Do Whatever you want
}
You will need to add preventDefault() to your form like so:
Add preventDefault() to your onSubmit event of your form:
<form onSubmit={e => e.preventDefault()}>
<input
type="text"
id=""
placeholder="Search"
onChange={e => {
setSearch(e.target.value);
}}
/>
</form>;
When clicked Enter, it triggers onSubmit(), default action is to refresh.
So to onSubmit() add preventDefault to overcome default behaviour.
Add the following line.
<form onSubmit={e => { e.preventDefault(); }}>
//code
</form>
The preventDefault() method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur.
For example, this can be useful when:
Clicking on a "Submit" button, prevent it from submitting a form
Clicking on a link, prevent the link from following the URL
const Test = () => {
const submit = (e) => {
e.preventDefault();
console.log('I am here without refresh the form!')
}
return <form onSubmit={submit}>
<input type = 'text' ></input>
</form>
}
ReactDOM.render( <Test/> ,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>
All you need is to add e.preventDefault();
to your onSubmit function to prevent your component from reloading.
However, I'll advise you to use React UI solutions like Ant Design which provides the feature out of the box and also allow you to write your code more efficiently.

React The function called in onSubmit in a form is not run

I am trying to create a form in react that should take what the user typed into the input field and then when submitted, it should direct the user to a new page.
For example: if the user typed Mike, it should redirect the user to /Mike
but when I click submit all that happens is that the input is added to the url as a parameter like localhost:3000/?query=Mike
Regarding malicious input I will probably deal with that when I fix this issue.
My code is as follows
function search({ history }) {
const [query, setQuery] = useState([]);
const handleSubmit = (e) => {
history.push(`/${query}`);
};
const handleChange = (text) => (e) => {
setQuery(e.target.value);
};
return (
<>
<form
onSubmit={(e) => e.handleSubmit()}
className=""
>
<div className="">
<span className="">
<i className="fas fa-search"></i>
</span>
<input
onChange={handleChange("query")}
type="text"
name="query"
className=""
/>
</div>
<button type="submit">Search</button>
</form>
</>
);
}
Unfortunately it looks like as though the function specified in the onSubmit is never called I have tried this by using console.log. What it does is reload the page and add ?query=<INPUT> to the URL
How can I fix this issue so that it redirects to the new page
Inside <form>, you're doing onSubmit={(e) => e.handleSubmit()}. You're calling the handleSubmit() of the event object, not your own handleSubmit function. Instead, try this:
function search({ history }) {
const [query, setQuery] = useState([]);
const handleSubmit = (e) => {
history.push(`/${query}`);
e.handleSubmit(); // if you still want to actually submit
};
const handleChange = (text) => (e) => {
setQuery(e.target.value);
};
return (
<>
<form
onSubmit={handleSubmit}
className=""
>
<div className="">
<span className="">
<i className="fas fa-search"></i>
</span>
<input
onChange={handleChange("query")}
type="text"
name="query"
className=""
/>
</div>
<button type="submit">Search</button>
</form>
</>
);
}

On cancel click not able to set previous data in my react app

I have created dynamic fields from JSON data, and I am successfully rendering on UI
Initially all the fields are disabled.
Once I click on edit I am making particular row editable which is working fine
On click of cancel what I want to do is make the fields disabled again and it should take the previous (initial value)
Issue
When I click on cancel I am setting the initial data aging but it is not taking, I am using react-form-hook for form validation, there we have reset() function but that too is not working.
What I am doing is
Getting data from main component and setting it to some state variable like below
useEffect(() => {
if (li) {
setdisplayData(li);
setCancelData(li);
}
}, [li]);
Now using displayData to render the elements
On click of Edit I am doing this
const Edit = () => {
setdisabled(false);
};
and on click of cancel I am doing below
const cancel = () => {
setdisabled(true); //disbaled true
console.log(cancelData);
setdisplayData(cancelData); setting my main data back to previous one
reset(); // tried this reset of react hook form but it did not work
};
I am using defaultValue so that when I click on Edit the field should allow me to edit.
Here is my full working code
To fix this issue I changed up your code to use value instead of defaultValue. Additionally added an onChange event handler which updates the displayData state whenever <input> changes value. Moreover, you do not need the cancelData state at all since the li prop has the original values.
Now when the onClick for the cancel button is fired, it resets the value of displayData state to whatever li originally was. Here is the modified code:
import React, { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
function component({ li, index }) {
const [disabled, setdisabled] = useState(true);
const [displayData, setdisplayData] = useState(null);
const { register, reset, errors, handleSubmit, getValues } = useForm();
useEffect(() => {
if (li) {
setdisplayData(li);
}
}, [li]);
const Edit = () => {
setdisabled(false);
};
const cancel = () => {
setdisabled(true);
console.log(li);
// Reset displayData value to li
setdisplayData(li);
reset();
};
return (
<div>
<div>
{disabled ? (
<button className="btn btn-primary" onClick={Edit}>
Edit
</button>
) : (
<button className="btn btn-warning" onClick={cancel}>
Cancel
</button>
)}
</div>
<br></br>
{displayData !== null && (
<>
<div className="form-group">
<label htmlFor="fname">first name</label>
<input
type="text"
name="fname"
disabled={disabled}
value={displayData.name}
// Update displayData.name everytime value changes
onChange={({ target: { value } }) =>
setdisplayData((prev) => ({ ...prev, name: value }))
}
/>
</div>
<div className="form-group">
<label htmlFor="lname">last name</label>
<input
type="text"
name="lname"
disabled={disabled}
value={displayData.lname}
// Update displayData.lname everytime value changes
onChange={({ target: { value } }) =>
setdisplayData((prev) => ({ ...prev, lname: value }))
}
/>
</div>
</>
)}
<hr></hr>
</div>
);
}
export default component;
Hope this helps. Drop a comment if it's still not clear :)

How to reset input field from useRef in React?

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

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