How to make ReactJS onClick function change the value of a textarea? - javascript

I am trying to make a ReactJS form in which there is a button which, once pressed, alters the value of an input tag. Every time I press the button, the text is changed, but the page reloads, and the textarea returns to being blank. I've searched up on this issue a little and found this thread : Reactjs every time refreshing page on setState.
However, the solution to this problem( shouldComponentUpdate() {return false;} ) ended up making it so that the text of the inputarea didn't change at all. Here is my code:
import React, { Component } from 'react';
export default class Header extends Component {
state = {
cep : "",
address : "",
}
searchCEP(){
this.setState({ address : "Adress" });
}
render(){
return (
<div>
<div id="host-form" className="row">
<div className="col s1"></div>
<form className="col s10">
<div className="row">
<div className="input-field col s6">
<input placeholder='"Terreno para churrasco"' id="title" type="text" className="validate"/>
<label htmlFor="title">Título</label>
</div>
<div className="input-field col s2">
<input id="cep" type="text" className="validate" defaultValue={this.state.cep}/>
<label htmlFor="cep">CEP</label>
</div>
<div id="buscar-cep" className="col s1">
<button onClick={() => this.searchCEP()} className="waves-effect blue waves-light btn">Buscar por CEP</button>
</div>
<div className="col s2"></div>
</div>
<div className="row">
<div className="input-field col s12">
<input placeholder='"Terreno de 500 metros quadrados com uma linda vista do Cristo Redentor...\"' id="description" type="text" className="validate"/>
<label htmlFor="description">Descrição</label>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<input id="address" type="text" className="validate" defaultValue={this.state.address}/>
<label htmlFor="address">Endereço</label>
</div>
</div>
</form>
</div>
</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>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I hope this is enough to understand my problem. Thanks in advance for any help.

from reading what you said the best case reason as to why the page reloads, from past exprience is that when you call the function you do not prevent the default action of the button within the form so you could try
"""
searchCEP(e){
e.preventDefault();
this.setState({ address : "Adress" });
}
"""
<div id="buscar-cep" className="col s1">
<button onClick={(e) => this.searchCEP(e)} className="waves-effect blue waves-light btn">Buscar por CEP</button>
</div>
"""
Since
hope this helps

You can make following changes
<div id="buscar-cep" className="col s1">
<button onClick={(e) => this.searchCEP(e)} className="waves-effect blue waves-light btn">Buscar por CEP</button>
</div>
and in searchCEP function, do the following changes:
searchCEP(e){
e.preventDefault();
this.setState({ address : "Adress" });
}
This will stop the reloading

You should stop the default behavior of the form element :
<form onSubmit={(e) => e.preventDefault()}

Related

How can I show/hide a form div in React.Component?

I am creating a CV Application project and I have a button that allows the user to Add Work Experience. When the user clicks the button a form pops up and they are able to fill the information out and click Submit.
I'm trying to make it so once the user hits Submit, the form div stays hidden until the user clicks Add Work Experience again. I've made something similar before in vanilla JS where I simply changed the forms class from display: block to display: none but that doesn't seem possible in React.
import React, { Component } from "react";
class WorkExperience extends Component {
render() {
const workExperience = [
{
title: "title",
company: "company",
location: "location",
description: "description",
},
];
return (
<>
<div id="content" className="content">
<h1 className="title">Work Experience</h1>
<div className="work-experience">
<p>Job Title: {workExperience[0].title}</p>
<p>Company: {workExperience[0].company}</p>
<p>Location: {workExperience[0].location}</p>
<p>Description: {workExperience[0].description}</p>
</div>
</div>
<button className="form-btn">+ Add Work Experience</button>
</>
);
}
}
export default WorkExperience;
And here is the form code I am currently using. This is the form I want to show/hide after clicking the Add Work Experience button shown above.
<form>
<label for="title">Job Title</label>
<input id="title" className="form-row" type="text" name="title" />
<label for="company">Company</label>
<input className="form-row" type="text" name="company" />
<label for="location">Location</label>
<input className="form-row" type="text" name="location" />
<label for="description">Job Description</label>
<textarea rows="4" cols="50" name="description"></textarea>
<button className="save">Save</button>
<button className="cancel">Cancel</button>
</form>
You can use an if statement or a ternary to return different jsx. That would look something like this. There are other ways as well, however this is a basic example of something you could do.
<>
{
shouldShow ?
(
<div id="content" className="content">
<h1 className="title">Work Experience</h1>
<div className="work-experience">
<p>Job Title: {workExperience[0].title}</p>
<p>Company: {workExperience[0].company}</p>
<p>Location: {workExperience[0].location}</p>
<p>Description: {workExperience[0].description}</p>
</div>
</div>
<button className="form-btn">+ Add Work Experience</button>
) : (
<form>
<label for="title">Job Title</label>
<input id="title" className="form-row" type="text" name="title" />
<label for="company">Company</label>
<input className="form-row" type="text" name="company" />
<label for="location">Location</label>
<input className="form-row" type="text" name="location" />
<label for="description">Job Description</label>
<textarea rows="4" cols="50" name="description"></textarea>
<button className="save">Save</button>
<button className="cancel">Cancel</button>
</form>
)
}
</>
Where shouldShow is what determines whether the form is showing or not.
The benefit to this is that if the form is showing, the other content is not added to the DOM and vice versa.
shouldShow would be a variable you could add to state, and when the button is clicked, you toggle the state variable, causing a re-render.
https://reactjs.org/docs/state-and-lifecycle.html
You could also choose to render styles depending on whether or not that component is showing, the key being that boolean state variable that is re-rendering the component.
Use Repeater Felilds to add User Work Experience. It's so easy to handle like this.
Repeater Component
import React from "react";
const Repeater = ({ inputFields, setInputFields }) => {
const handleFormChange = (index, event) => {
let data = [...inputFields];
data[index][event.target.name] = event.target.value;
setInputFields(data);
};
const removeFields = (index) => {
let data = [...inputFields];
data.splice(index, 1);
setInputFields(data);
};
return (
<div className="row">
{inputFields.map((input, index) => {
return (
<>
<div className="form-group col-sm-12 col-md-4 mb-3">
<div className="controls">
<input
type="text"
className="form-control inputset"
id="title"
placeholder="title"
name="title"
data-validation-required-message="This field is required"
aria-invalid="true"
required
value={input.title}
onChange={(event) => handleFormChange(index, event)}
/>
<div className="help-block" />
</div>
</div>
<div className="form-group col-sm-12 col-md-4 mb-3">
<div className="date-picker">
<input
type="text"
className="pickadate form-control inputset"
value={input.company}
onChange={(event) => handleFormChange(index, event)}
name="company"
id="pass"
data-validation-required-message="This field is required"
data-toggle="tooltip"
data-trigger="hover"
data-placement="top"
data-title="Date Opened"
data-original-title=""
required
/>
</div>
</div>
<div className="form-group col-sm-12 col-md-4 d-flex mb-3">
<input
type="text"
className="form-control inputset"
id="location"
placeholder="location"
name="location"
data-validation-required-message="This field is required"
aria-invalid="true"
required
value={input.location}
onChange={(event) => handleFormChange(index, event)}
/>
<input
type="text"
className="form-control inputset"
id="description"
placeholder="description"
name="description"
data-validation-required-message="This field is required"
aria-invalid="true"
required
value={input.description}
onChange={(event) => handleFormChange(index, event)}
/>
{inputFields.length === 1 ? null : (
<button
type="button"
className=" d-flex justify-content-center align-items-center ml-1 btn"
onClick={() => {
removeFields();
}}
>
<i className="uil-trash-alt" />
</button>
)}
</div>
</>
);
})}
</div>
);
};
export default Repeater;
Main Component
use these as states and pass the objects to the Repeater Component. First, the state is empty and when the user clicks on the button Add More Experience The files auto-show.
const [inputFields, setInputFields] = useState([
{ degree_title: "", institue: "", end_date: "" },
]);
const addFields = () => {
let newfield = { degree_title: "", institue: "", end_date: "" };
setInputFields([...inputFields, newfield]);
};
<Repeater
inputFields={inputFields}
setInputFields={setInputFields}
addFields={addFields} />
I wish this solution helps you :) Make sure to change the state object according to your requirements.

ReCaptcha not showing up

I'm trying to display a simple ReCaptcha. However, it appears if I delete onloadCallback function and then re-add it. Then it disappears until I do this again.
I will attach the code that I use. Also, I add localhost as a domain and I install the package using npm. I will write hidden instead of the site key that I use. Also, I want to hide my submit form button if the ReCaptcha is not verified, for this, I use useState hooks.
import React, { useState, useEffect } from 'react';
import ReCAPTCHA from "react-google-recaptcha";
import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import { collection, addDoc } from "firebase/firestore";
import {db} from "./firebase.js"
export default function Contact(){
const [captcha, setCaptcha] = useState(true);
const [formData, setFormData] = useState({
name: "",
phone: "",
subject: "",
message: ""
})
function handleOnChange(value){
setCaptcha(false);
console.log("recaptcha ", value);
}
function recaptchaLoaded() {
console.log('capcha successfully loaded');
}
function handleOnChange(value){
console.log("captcha value:" , value);
}
function handleChange(event){
const {name, phone, subject, message} = event.target
setFormData(prevFormData => ({
...prevFormData,
[event.target.name]: event.target.value
}))
}
function handleSubmit(event){
event.preventDefault();
try {
console.log(formData);
const docRef = addDoc(collection(db, "mesaje"), { formData });
console.log("Document written with ID: ", docRef.id);
} catch (e) {
console.error("Error adding document: ", e);
}
}
return(
<section id="contact" class="contact">
<div class="container">
<div class="section-title" data-aos="zoom-out">
<h2>Contact</h2>
<p>Date de contact</p>
</div>
<div class="row mt-5">
<div class="col-lg-4" data-aos="fade-right">
<div class="info">
<div class="address">
<i class="bi bi-geo-alt"></i>
<h4>Locatie:</h4>
<p>Galati</p>
</div>
<div class="email">
<i class="bi bi-envelope"></i>
<h4>Email:</h4>
<p>carageamarian72#yahoo.com</p>
</div>
<div class="phone">
<i class="bi bi-phone"></i>
<h4>Telefon:</h4>
<p>0744635351</p>
</div>
</div>
</div>
<div class="col-lg-8 mt-5 mt-lg-0" data-aos="fade-left">
<form onSubmit={handleSubmit} class="php-email-form" >
<div class="row">
<div class="col-md-6 form-group">
<input type="text" name="name" class="form-control" id="name" placeholder="Nume" required onChange={handleChange}
value={formData.name}/>
</div>
<div class="col-md-6 form-group mt-3 mt-md-0">
<input type="tel" class="form-control" name="phone" id="phone" placeholder="Telefon" required onChange={handleChange}
value={formData.phone} pattern="[0-9]{10}"/>
</div>
</div>
<div class="form-group mt-3">
<input type="text" class="form-control" name="subject" id="subject" placeholder="Subiect" required onChange={handleChange}
value={formData.subject}/>
</div>
<div class="form-group mt-3">
<textarea class="form-control" name="message" rows="5" placeholder="Mesaj" required onChange={handleChange}
value={formData.message}></textarea>
</div>
<div class="my-3">
<div class="loading">Loading</div>
<div class="error-message">Eroare, mesajul nu a fost trimis!</div>
<div class="sent-message">Mesajul a fost trimis, te vom contacta imediat!</div>
</div>
<ReCAPTCHA
sitekey="hidden"
onChange={handleOnChange}
onloadCallback={recaptchaLoaded}
/>
<div class="text-center"><button type="submit" disabled={captcha}>Trimite mesaj</button></div>
</form>
</div>
</div>
</div>
</section>
);
}
i found the problem. I had 2 different types of recaptcha in my html folder. They were in conflict.
I also delete the onloadCallback props.

How to redirect another page after button on click method react js [duplicate]

This question already has an answer here:
Problem in redirecting programmatically to a route in react router v6
(1 answer)
Closed 11 months ago.
This is the my login.js page code I want redirect the new page after click the button. I tried several methods but problem not solve. All things are work correctly. but I don't know how to link the page after the api return result in loginClick function. I Added this line in the code refer some tutorial but its not work.
this.props.history.push('/add');
I am new to the react js, I don't know about the react well. please help me.
import React,{Component} from 'react';
import { variables } from '../../Variables';
export class Login extends Component{
constructor(props){
super(props);
this.state={
login:[],
name:"",
password:"",
redirect: false
}
}
changelogindetailsname = (e)=>{
this.setState({name:e.target.value})
}
changelogindetailspass = (e)=>{
this.setState({password:e.target.value})
}
loginClick(){
fetch(variables.API_URL+'login',{
method:'POST',
headers:{
'Accept':'application/json',
'Content-Type':'application/json'
},
body:JSON.stringify({
name:this.state.name,
password:this.state.password
})
})
.then(res=>res.json())
.then((result)=>{
alert(result);
this.props.history.push('/add');
},(error)=>{
alert('Faild');
})
}
render(){
const{
name,
password
}=this.state;
return(
<div>
<center>
<h1></h1>
<hr/>
<h3>Welcome Back !</h3>
<p></p>
<div className="container">
<br/>
<br/>
<br/>
<div className="row">
<div className="col">
</div>
<div className="col">
</div>
<div className="col-4">
<style>{"\ .rr{\ float:left;\ }\ "} </style>
<style>{"\ .bb{\ float:right;\ }\ "} </style>
<div className="mb-3">
<label className="form-label rr d-flex"> Username</label>
<div className="input-group input-group-lg">
<input type="text" className="form-control " id="formGroupExampleInput" placeholder="Username"
value={name}
onChange={this.changelogindetailsname}/>
</div>
</div>
<div className="mb-3">
<label className="form-label rr d-flex">Password</label>
<div className="input-group input-group-lg">
<input type="password" className="form-control" id="formGroupExampleInput2" placeholder="Password"
value={password}
onChange={this.changelogindetailspass}/>
</div>
</div>
<div className="d-flex mb-3">
Forgot your password?
</div>
<div className="col">
<div className="form-check rr">
<input className="form-check-input" type="checkbox" value="" id="flexCheckDefault"/>
<label className="form-check-label" htmlFor="flexCheckDefault">
Remember me
</label>
</div>
</div>
<div className="col">
<button type="button" className="btn btn-success bb"
onClick={()=>this.loginClick() } >Login</button>
</div>
<br/>
<br></br>
<hr/>
<p>Don't have an account?</p>
<div className="mb-3">
<button type="button" className="btn btn-light d-flex"
>Sign up for Muessoze</button>
</div>
</div>
<div className="col">
</div>
<div className="col">
</div>
</div>
</div>
</center>
</div>
)
}
}
Firstly you should import this:
import { useHistory } from 'react-router-dom';
then:
const history = useHistory();
after all, you can use this in your method:
loginClick(){
fetch(variables.API_URL+'login',{
method:'POST',
headers:{
'Accept':'application/json',
'Content-Type':'application/json'
},
body:JSON.stringify({
name:this.state.name,
password:this.state.password
})
})
.then(res=>res.json())
.then((result)=>{
alert(result);
history.push('/add');
},(error)=>{
alert('Faild');
})
}
Take a look at the react router API, if you want to use the this.props.history.push() method you will need to wrap your component with the withRouter HOC wrapper from the react dom api.
See : https://reactrouter.com/docs/en/v6/getting-started/tutorial

v-if and v-else not working because updating page every time

I have the issue that the div in the v-if statement is not correctly working. If you run the server and the page when you click the button Sign Up it will briefly showing the div for signing up but it will get back the the original div in the first v-if statement after few seconds.
Instead I expect that it would show just show the div in the v-else because I am changing the boolean showSignUp with the v-on:click="signUp" which will call the function in the Vue App that will change the boolean.
This is the HTML :
<body onload="init()">
<!-- using the Vue App -->
<div id="app">
<!-- If it is not signed in just make it sign -->
<div v-if="!isLoggedIn" class="container-fluid">
<!-- Top Bar -->
<div class="row align-items-center justify-content-start">
<nav class="navbar navbar-light bg-light">
<h1>UST Computer Science Submission Tool</h1>
</nav>
</div>
<div class="row align-items-center justify-content-end">
<div v-if="!showSignUp">
<form class="getSpace" > <!-- SIGN IN FORM -->
<!-- Input fields -->
<div class="form-group">
<label for="inputEmail">Email address</label>
<input type="email" class="form-control" id="inputEmail">
</div>
<div class="form-group">
<label for="inputPassword">Password</label>
<input type="password" class="form-control" id="inputPassword">
</div>
<!-- Buttons -->
<button v-on:click="signIn" class="btn btn-primary">Sign In</button>
<button v-on:click="signUp" class="btn btn-primary">Sign Up</button>
</form>
</div>
<div v-if="showSignUp">
<form class="getSpace"> <!-- SIGN UP FORM -->
<!-- Input fields -->
<div class="form-group">
<label for="inputEmail">Email address</label>
<input type="email" class="form-control" id="singUpEmail">
</div>
<div class="form-group">
<label for="inputPassword">Password</label>
<input type="password" class="form-control" id="singUpInputPassword">
</div>
<!-- Buttons -->
<button v-on:click="submitRegistration" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
<!-- Else is already signed in -->
<div v-else class="container-fluid">
<div class="row">
<div class="col">You did it</div>
<div class="col"></div>
</div>
</div>
</div>
</body>
This is the JS for the Vue App:
let app
// On loading page
function init() {
app = new Vue({
el: '#app',
data: {
email: '',
password: '',
isLoggedIn: false,
showSignUp: false
},
methods: {
signIn: signIn,
signUp: signUp,
submitRegistration: submitRegistration,
}
});
}
// methods
function signIn(event) { // when clicked Sing In button
// check before in the data base if it is correct
// Now show the Users page
app.isLoggedIn = !app.isLoggedIn;
}
function signUp (event) { // when clicked Sing Up button
// This will change the form
console.log('was here');
app.showSignUp = true;
}
function submitRegistration (event) {
console.log(event);
// Call http
}
you need to prevent the action
<button v-on:click.prevent="signUp" class="btn btn-primary">Sign Up</button>

ReactJs form onSubmit handle not working

I have a ReactJs component. handleSubmit is not called when my form is submitted. I am using meteorJs as my backend and ReactJs as my frontend library. I don't know where is the problem. I tried commenting out everything except input tag but didn't work.
import React, {Component} from 'react';
export default class ConfessionPoster extends Component {
constructor(props) {
super(props);
this.state = {
value: ''
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
//handle form submit
handleSubmit(event) {
event.preventDefault();
console.log("We are in handle");
console.log(this.state.value);
}
handleInputChange(event) {
event.preventDefault();
// const target = event.target;
// const confessionValue = target.value;
// const confessionName = target.name;
//
// this.setState({[confessionName]: confessionValue});
// console.log(this.state.confessionText);
this.setState({value: event.target.value});
console.log(this.state.value);
}
render() {
return (
<div id="confession-poster" className="modal">
<div className="modal-content">
<div className="row">
<div className="col s1">
<i className="material-icons prefix">account_circle</i>
</div>
<div className="col s11">
<h6>Kiran Kumar Chaudhary</h6>
</div>
</div>
<form onSubmit={this.handleSubmit}>
<div className="row confession-area">
<div className="input-field col s12">
<label htmlFor="confession-textarea">Your Confession</label>
<textarea id="confession-textarea" className="materialize-textarea" value={this.state.value} onChange={this.handleInputChange}/>
</div>
</div>
<div className="row">
<div className="col s12">
<i className="material-icons">photo_camera</i>
<i className="material-icons">link</i>
<i className="material-icons">location_on</i>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<input type="checkbox" className="filled-in" id="hide-my-identity" defaultChecked/>
<label htmlFor="hide-my-identity">Hide my Identity</label>
</div>
</div>
<div className="row">
<input className="btn" type="submit" value="Post"/>
</div>
</form>
</div>
</div>
);
}
}

Categories