cannot clear form field with functional react hook in reactjs - reactjs

The code below works fine by submit a post message. now i want to clear the message input form on form submission but cannot get it to work. I have tried the following 3 options but yet no luck.
1.)
function clearState() {
message('');
}
// pass the clear state function on form submission
clearState();
2.) Clear form by referencing the form id
document.getElementById('my_form').reset();
3.) using event target reset
event.target.reset();
here is the full code.
import React, { useState, useRef, useEffect } from "react";
export default function App(props) {
const [message, setMessage] = useState("");
const [messages, setMessages] = useState([]);
const currentDate = new Date();
useEffect(() => {
// fetch content axio or ajax
}, []);
function clearState() {
message('');
}
function handleChange(event) {
setMessage(event.target.value);
}
function handleSubmit(event) {;
event.preventDefault();
const newMessages = messages;
const data = { message: message, date: new Date() };
setMessages(newMessages.concat([data]));
//clear all form field based on form id
clearState();
//document.getElementById('my_form').reset();
//event.target.reset();
}
return (
<React.Fragment>
<div className="chat_container">
{messages.map((m, e) => (
<div key={e}>
<div className="chat_message">
chat: {m.message} ---{m.date.toLocaleTimeString()}
</div>
</div>
))}
</div>
<div className="myFooter">
<form id"my_form" onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={message} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
</React.Fragment>
);
}

Related

React onClick button is not triggering the function

I am developing an chrome extension where i need to authentication user but a very simple onClick button which calls a function is not working
this is the simple code where i want to show info on console when button is clicked
import React, { useState } from 'react';
const Login = () => {
const [user, setuser] = useState("");
const handleSubmit = (data) => {
data.preventDefault();
console.log("usernae: ");
console.log("Data: ", data.target);
}
const getInputValue = (event) => {
console.log(event.target.value)
// Select input element and get its value
console.log("I am heresdfg")
// let inputVal = document.getElementsByClassName("usernameInputField")[0].value;
// Display the value
// alert(inputVal);
}
return (
<div
id="login-form">
<p>
<div className='form'>
</div>
<input type="text"
id="username"
name="username"
className='usernameInputField'
value={user}
onChange={(event => setuser(event.target.value))}
placeholder="Username" required />
</p>
<p>
<button onClick={getInputValue} type="button" id="login">button</button>
</p>
</div>
);
};
export default Login;
It seems like you want the input value value inside the event handler if I'm not wrong, you can get it from the state - user as
const getInputValue = (event) => {
console.log(user)
}
as the event would be button's you wouldn't get the value of input from it's event and it is not required too as it's already in the react's state ....
Example:
const {useState} = React;
const App = () => {
const [name, setName] = useState("");
const submitHandler = () => {
console.log(name)
}
return (
<div>
Name: <input type="text" value={name} onChange={(e)=>setName(e.target.value)}/>
<button onClick={submitHandler}>Submit</button>
</div>
);
};
ReactDOM.createRoot(
document.getElementById("root")
).render(
<App/>
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
In the getInputValue function event is pointing to the button.
Change the event.target.value to user if you want to print the text into the console.
Here's the codesandbox.
If you don't want to use the value from useState then you can also check useRef hook which works in a similar way.

React submitting form does not re-render

I am making 2 react components (PlayerSearch for sumbitting a form containing target player's name, and PlayerAPI for fetching request). I want it to re-render PlayerAPI everytime I hit the submit button OR everytime the submitted data is updated. So my code looks like this:
In PlayerSearch:
export function PlayerSearch() {
const [formData, setFormData] = useState({ APIkey: "", name: "" });
const [submittedData, setsubmittedData] = useState({ submittedAPIkey:"", submittedname:"" });
const onChange = (event) => {
setFormData({ ...formData, [event.target.name]: event.target.value });
};
function handlesubmit(e) {
e.preventDefault();
setsubmittedData({ ...submittedData, submittedAPIkey: formData.APIkey, submittedname: formData.name });
}
return <div className='player'>
<div className='inputfield'>
<form onSubmit={handlesubmit} method='GET' autoComplete="off">
<div>
<label htmlFor="APIkey">Your API key:</label>
<input placeholder='Your API key' onFocus={(e)=>{e.target.placeholder=''}} type="text" id="APIkey" name="APIkey" value={formData.APIkey} onChange={onChange}/>
</div>
<div>
<label htmlFor="name">Player name:</label>
<input placeholder='Player name' onFocus={(e)=>{e.target.placeholder=''}} type="text" id="name" name="name" value={formData.name} onChange={onChange}/>
</div>
<div>
<button type='submit'>Submit</button>
</div>
</form>
</div>
<div id='result'>
//This is where I render the PlayerAPI
{(submittedData.submittedAPIkey !== "" && submittedData.submittedname !== "") && <PlayerAPI APIkey={submittedData.submittedAPIkey} name={submittedData.submittedname} />}
</div>
</div>
}
Edit: I've found out that the form submit is not the problem. The problem is in the PlayerAPI and I fixed it.
The PlayerAPI before:
export function PlayerAPI(props) {
const [data, setdata] = useState({ accountId: ''});
const getPlayerID = async () => {
//some API fetching...
}
useEffect(()=>{
getPlayerID();
},[]);
return <div>
<div className='SearchResult'>
hello {JSON.stringify(data)}
</div>
</div>;
}
The PlayerAPI now:
import { useEffect, useState } from "react";
export function PlayerAPI(props) {
const [data, setdata] = useState({ accountId: ''});
const getPlayerID = async () => {
//some API fetching...
}
useEffect(()=>{
getPlayerID();
},[props.name, props.APIkey]);
return <div>
<div className='SearchResult'>
hello {JSON.stringify(data)}
</div>
</div>;
}
maybe this solution will help? Setting onSubmit in React.js
moving the e.preventDefault(); to the end of the handleSubmit
I've found out that the form submit is not the problem. The problem is in the PlayerAPI and I fixed it.
The PlayerAPI before:
export function PlayerAPI(props) {
const [data, setdata] = useState({ accountId: ''});
const getPlayerID = async () => {
//some API fetching...
}
useEffect(()=>{
getPlayerID();
},[]);
return <div>
<div className='SearchResult'>
hello {JSON.stringify(data)}
</div>
</div>;
}
The PlayerAPI now:
import { useEffect, useState } from "react";
export function PlayerAPI(props) {
const [data, setdata] = useState({ accountId: ''});
const getPlayerID = async () => {
//some API fetching...
}
useEffect(()=>{
getPlayerID();
},[props.name, props.APIkey]);
return <div>
<div className='SearchResult'>
hello {JSON.stringify(data)}
</div>
</div>;
}
So apparently somehow I thought that hitting the submit button again would activate the initial render of useEffect in PlayerAPI so I left the dependency array empty.

setState on submit and not onChange

I have a form, where I use the input from the input fields to send to a back-end.
For example, I have a variable looking something like this:
const [data, setData] = useState([])
const [inputField, setInputField] = useState()
Then I have a form that looks something like this:
<form onSubmit={fetchData}>
<input type="number" value={value} onChange={(e) => setInputField(e.target.value)} />
<button type="submit">Fetch data</button>
</form>
The fetchData is given by:
function fetchData(e?: any) {
e?.preventDefault();
POST("/api", {
inputField: inputField,
}).then(async (response) => {
const json = await response.json();
setData({
retrievedData: json.retrievedData,
});
});
}
I have other forms as well, where this onChange updating is good, but for some input fields I don't need it do update/re-render before the actual submit button that triggers the form are clicked.
So how do I update the state of the inputField when the button is clicked, instead of now where it updates every time I write a new character in the input field ?
Try this
import {useRef } from "react";
export const Temp = () => {
const inputField = useRef(null);
const onBtnClick = () => {
alert(inputField?.current?.value);
};
return (
<div>
<input type="text" ref={inputField} />
<button type="submit" onClick={onBtnClick}>
Fetch data
</button>
</div>
);
};
You can use useRef hook for that.
const inputNumber = useRef();
<input
ref={inputNumber}
id="number"
placeholder="33xx"
type="number"
/>
Then on button click you can get the value like that
inputNumber.current?.value,
You don't need a state for that and you don't even need a ref. You can get the form values directly from the submit event (event.target.<input name>.value). You will need to add the name property to the <input /> to make it accessible from the event target. Please, find the example below:
function Form() {
const [data, setData] = React.useState();
const onSubmit = (e) => {
e.preventDefault();
const inputField = e.target.inputField.value;
POST("/api", {
inputField: inputField,
}).then(async (response) => {
const json = await response.json();
setData({
retrievedData: json.retrievedData,
});
});
};
return (
<form onSubmit={onSubmit}>
<input type="text" name="inputField" />
<button type="submit">Submit</button>
</form>
);
}
ReactDOM.render(
<Form />,
document.getElementById("root")
);
<div id="root"></div>
<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>

Display user input value upon submit in react

I want the user to input some text, click submit and the text will be displayed below.
I was able to get the input text as a whole, and print it in console. But I don't know how to display the text.
Here's my code:
https://codesandbox.io/s/ecstatic-curie-ej6og?file=/src/App.js
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [enteredText, setEnteredText] = useState("");
const textChangeHandler = (i) => {
setEnteredText(i.target.value);
//console.log(i.target.value);
};
const submitHandler = (event) => {
event.preventDefault();
const x = enteredText;
console.log(x);
setEnteredText("");
};
return (
<div className="App">
<h1>Get user input</h1>
<form onSubmit={submitHandler}>
<input
placeholder="type something"
type="text"
value={enteredText}
onChange={textChangeHandler}
/>
<button type="submit" >
Submit
</button>
</form>
<p>You just typed: {x}</p> // This is wrong. x is out of scope. But i'm not sure how to write this line.
</div>
);
}
You can use an additional state variable to store the "submitted text". You would update that new state variable with the text from the enteredText state variable before emptying it. You could also make sure the "submitted text" has a value before displaying it.
I am including code that does what I described, but you can also try implementing it on your own before looking at it:
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [enteredText, setEnteredText] = useState("");
const [submittedText, setSubmittedText] = useState(null);
const textChangeHandler = (i) => {
setEnteredText(i.target.value);
//console.log(i.target.value);
};
const submitHandler = (event) => {
event.preventDefault();
setSubmittedText(enteredText);
setEnteredText("");
};
return (
<div className="App">
<h1>Get user input</h1>
<form onSubmit={submitHandler}>
<input
placeholder="type something"
type="text"
value={enteredText}
onChange={textChangeHandler}
/>
<button type="submit" >
Submit
</button>
</form>
{submittedText && (<p>You just typed: {submittedText}</p>)}
</div>
);
}

React.js setState not getting update wiith onclick

This is my sample code, it's very basic i just want to console fname once submit is clicked.
When i pressed first time i get an empty line but when pressed second time the button i get some empty value. I am attaching the screenshot for the console.
I dont want to change my code to a class and use some method to get the value in console.
screenshot for console output
import React,{useState} from 'react'
export const anyComponent = () => {
const [fname, setFname] = useState('')
const submit = (event) =>{
setFname({fname: [event.target.value] })
console.log(fname)
}
return(
<div>
<input name="fname" type="text" placeholder="Enter your First Name" />
<button onClick={submit}>Submit</button>
</div>
)
}
From MDN Docs:
The target property of the Event interface is a reference to the object onto which the event was dispatched.
In your case, event.target would point to the button and not input.
What you need is a reference to the input, you can use useRef hook for it like this
import React, { useState, useRef } from "react";
export default anyComponent = () => {
const inputEl = useRef(null);
const [fname, setFname] = useState("");
const submit = event => {
setFname({ fname: [inputEl.current.value] });
};
console.log(fname);
return (
<div>
<input
name="fname"
ref={inputEl}
type="text"
placeholder="Enter your First Name"
/>
<button onClick={submit}>Submit</button>
</div>
);
};
Also, setState is asynchronous, that's why you wouldn't see the result in the console just after calling setFname. However you'd see the updated fName in console on the next render, that's why I've moved it out of the submit.
Without useRef
Alternatively, you can add onChange handler on input and update the state fname from there
function App(){
const [fname, setFname] = useState("");
const submit = () => {
console.log(fname);
};
const handleChange = ev => {
setFname({ fname: [ev.target.value] });
}
return (
<div>
<input
name="fname"
onChange={handleChange}
type="text"
placeholder="Enter your First Name"
/>
<button onClick={submit}>Submit</button>
</div>
);
};
Your console log should be outside submit method. Or log event.target.value instead fname.

Resources