I just want to know, how to show a anything in a HTML body when the button is clicked. Is there anythin like echo in php
this is my appTodo.js code....
import React, { useState } from 'react'
export default function AddTodo() {
const [input, setInput] = useState("");
const onChange = (e) => {
setInput(e.target.value)
}
const handleOnClick = () => {
console.log(input)
setInput("")
}
return (
<div className='container my-3 col-6'>
<form>
<input className="form-control" onChange={onChange} type="text" placeholder="What to do?" value={input} />
<button id='addbtn' onClick={handleOnClick} type="button" className="btn btn-dark my-3">Add</button>
</form>
</div>
)
}
Just you need to create one variable to keep the state of the visibility of the div.
import React, { useState } from 'react'
export default function AddTodo() {
const [input, setInput] = useState("");
const [divVisibility, setDivVisibility] = useState(false);
const onChange = (e) => {
setInput(e.target.value)
}
const handleOnClick = () => {
setInput("")
setDivVisibility(true)
}
return (
<div className='container my-3 col-6'>
<form>
<input className="form-control" onChange={onChange} type="text" placeholder="What to do?" value={input} />
<button id='addbtn' onClick={handleOnClick} type="button" className="btn btn-dark my-3">Add</button>
</form>
{divVisibility &&
<div>
Your content
</div>
}
</div>
)
}
This code makes a state that can be changes between true and false by clicking the button. When false "componenet" = null, and when true "component" = (your component).
const [visible, setVisible] = useState(false);
function makeVisible() {
if(visible === false){
setVisible(true)
} else setVisible(false);
}
const component = visible == true ? <h1>SHOWN</h1> : null;
const buttonString = visible == true? "UnShow" : "Show"
return (
<div className="App">
<h1>Hello World!</h1>
{component}
<button onClick={makeVisible} >{buttonString}</button>
</div>
);
}
Related
I am trying to show error message if client did not click checkbox, but it shows the error message by default.
How do I manage to show it only after submission?
const InputForm=()=>{
const [value ,setValue] = useState("");
const [check,setCheck] = useState(null)
const getValue=(e)=>{
setValue(e.target.value);
}
const getCheck=(e)=>{
setCheck(e.target.checked);
}
const handleSubmit=(e)=>{
e.preventDefault();
const emailValidator =/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/
if (value.match(emailValidator)) {
console.log("Valid");
}else{
console.log("Invalid");
}
};
return(
<form className="inputForm" onSubmit={handleSubmit}>
<div className="tos" >
<label className="container">
<span>I agree to <strong>terms of service</strong></span>
<input type="checkbox" onChange={getCheck}/>
<span className="checkmark" ></span>
</label>
<p style={check?{display:"none"}:{display:"block",color:"red"}}>You must accept the terms and conditions</p>
</div>
<Footer/>
</form>
)
};
import { useEffect, useState } from "react";
export default function App() {
const [checked, setChecked] = useState(null);
const [error, setError] = useState(false);
useEffect(() => {
checked && setError(false);
}, [checked, setError]);
const handleSubmit = (e) => {
e.preventDefault();
if (!checked) {
setError(true);
} else {
// do what you want
}
};
return (
<form className="inputForm" onSubmit={handleSubmit}>
<div className="tos">
<label className="container">
<span>
I agree to <strong>terms of service</strong>
</span>
<input
type="checkbox"
onChange={(e) => setChecked(e.target.checked)}
/>
<span className="checkmark"></span>
</label>
{error && (
<p style={{ color: "red" }}>
You must accept the terms and conditions
</p>
)}
</div>
<button type="submit">submit</button>
</form>
);
}
<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>
Here is a solution :
https://codesandbox.io/s/crimson-field-m6j5h?file=/src/App.js
You should have a separate state for the error and render the message only if that state is truthy.
That state should be set when calling you handleSubmit function.
To remove the error message when the checkbox is checked, you can listen to it in a useEffect hook.
I have a React form with dynamic input fields that a user can add and remove input fields. When i submit the form, i log the values from each input in an array. The problem is that i can't type continuously in a input. When i type in input, i can type only one character and it focus out. How can i fix it?
CodeSandbox
App.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [fields, setFields] = useState([""]);
function handleChange(i, event) {
const values = [...fields];
values[i] = event.target.value;
setFields(values);
}
function handleAdd() {
const values = [...fields];
values.push("");
setFields(values);
}
function handleRemove(i) {
const values = [...fields];
values.splice(i, 1);
setFields(values);
}
function submitHandler(event) {
event.preventDefault();
console.log(fields);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<form onSubmit={submitHandler}>
<button type="button" onClick={() => handleAdd()}>
Add Input
</button>
{fields.map((field, idx) => {
return (
<div key={`${field}-${idx}`}>
<input
type="text"
placeholder="Enter text"
value={field || ""}
onChange={(e) => handleChange(idx, e)}
/>
<button type="button" onClick={() => handleRemove(idx)}>
X
</button>
</div>
);
})}
<button className="margin-top" type="submit">
Submit
</button>
</form>
</div>
);
}
export default App;
Replace your code with this
<div key={`${"asdf"}-${idx}`}>
<input
type="text"
placeholder="Enter text"
value={field || ""}
onChange={(e) => handleChange(idx, e)}
/>
<button type="button" onClick={() => handleRemove(idx)}>
X
</button>
</div>
i have used a third party debounce , you can choose anything you want
code
import React, { useState } from "react";
import AwesomeDebouncePromise from "awesome-debounce-promise";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [fields, setFields] = useState([""]);
function handleChange(i, event) {
const values = [...fields];
values[i] = event.target.value;
setFields(values);
}
function handleAdd() {
const values = [...fields];
values.push("");
setFields(values);
}
function handleRemove(i) {
const values = [...fields];
values.splice(i, 1);
setFields(values);
}
const searchAPIDebounced = AwesomeDebouncePromise((event) => {
console.log(fields);
}, 100);
const submitHandler = async (event) => {
event.preventDefault();
const result = await searchAPIDebounced(event);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<form onSubmit={submitHandler}>
<button type="button" onClick={() => handleAdd()}>
Add Input
</button>
{fields.map((field, idx) => {
return (
<div key={`${idx}`}>
<input
type="text"
placeholder="Enter text"
value={field || ""}
onChange={(e) => handleChange(idx, e)}
/>
<button type="button" onClick={() => handleRemove(idx)}>
X
</button>
</div>
);
})}
<button className="margin-top" type="submit">
Submit
</button>
</form>
</div>
);
}
export default App;
I have here 2 JS files here (React JS) and a small error. The idea is that this application is an TodoList and an element is created by clicking on the respective button. It works well but every time I add a new element, the color of the li stays the same. It doesn't move after that LI.
App.js
import React, { useState, useRef } from "react"
import ItemToDo from "./ItemToDo"
import "./style.scss"
export default function App() {
const [items, setItems] = useState([])
const [currentMap, setMap] = useState()
const inputRef = useRef()
const addElement = () => {
if (inputRef.current.value === "") {
alert("Please enter something...")
} else {
items.unshift(inputRef.current.value)
setItems(items)
console.log(items)
inputRef.current.value = ""
updateMap()
}
}
const updateMap = () => {
setMap(items.map((item, key) => <ItemToDo key={key} item={item} removeElement={() => removeElement(key)} />))
}
const removeElement = (index) => {
delete items[index]
updateMap()
}
const handleKey = (e) => {
if (e.key === 'Enter') {
addElement()
}
}
return (
<>
<h1>ToDo List</h1>
<input type="text" placeholder="Name here" ref={inputRef} id="elementName" onKeyDown={handleKey} autoFocus />
<input type="button" value="Add Item" id="submit" onClick={addElement} />
<div>
<ul>
{currentMap}
</ul>
</div>
</>
)
}
and ItemToDo.js
import React, {useState} from "react"
export default function ItemToDo({item, removeElement}) {
const [color, setColor] = useState(true)
const setBackground = () => {
setColor(false)
}
return (
<li style={{backgroundColor: color ? "green" : "red"}}>
<span>{item}</span>
<input type="button" value="Delete" onClick={removeElement} />
<input type="button" value="Done!" onClick={() => setBackground()} />
</li>
)
}
And I want to fix this bug... Basically if I add a new element the red color stays there.
Thanks in advance for any idea!
I want to transfer a variable from search component as "child" to API component as "Parent". I did it with event for another part of codes but I don't know how did work exactly for a variable on my codes.
I want send "apiUrl" to parent. When user click on "current" get new location and generate new apiUrl, then send it to parent component for other stuff
Child:
import React from "react";
import "./Search.css";
const Search = function (props) {
const handleChange = (event) => {
props.onchange(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
props.onsubmit(event.target.value);
};
const navigation = (event) => {
event.preventDefault();
navigator.geolocation.getCurrentPosition(showPosition);
};
const showPosition = (position) => {
let latitude = position.coords.latitude;
let longitude = position.coords.longitude;
let latandlon = `lat=${latitude}&lon=${longitude}`;
let apiKey = "23422500afd990f6bd64b60f46cf509a";
let unit = "metric";
let apiUrl = `https://api.openweathermap.org/data/2.5/weather?${latandlon}&appid=${apiKey}&units=${unit}
`;
};
return (
<form className="form" onSubmit={handleSubmit}>
<div className="input-group">
<input
type="search"
className="form-control me-1"
placeholder="Enter City Name"
aria-label="City Name"
aria-describedby="basic-addon2"
onChange={handleChange}
/>
<div className="input-group-append">
<button className="btn btn-outline-secondary me-1" type="submit">
Search
</button>
<button
className="btn btn-outline-secondary me-1"
type="button"
onClick={navigation}
>
Current
</button>
</div>
</div>
</form>
);
};
export default Search;
Parent:
import React, { useState, useEffect } from "react";
import axios from "axios";
import Search from "./Search";
import ShowCurrentLocation from "./ShowCurrentLocation";
import HumidityAndWind from "./HumidityAndWind";
import CurrentStatus from "./CurrentStatus";
import ShowCurrentDay from "./ShowCurrentDay";
import CurrentDegree from "./CurrentDegree";
const Api = function (props) {
let [searchcity, setSearchcity] = useState("Tehran");
const [value, setValue] = useState("");
const [loader, setLoader] = useState(false);
const [weatherdata, setWeatherdata] = useState("");
const onchange = (data) => {
setValue(data);
};
const onsubmit = () => {
setSearchcity(value);
searchcity = value;
callApi();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(callApi, []);
function callApi() {
const apiKey = "23422500afd990f6bd64b60f46cf509a";
let units = "metric";
let apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${searchcity}&appid=${apiKey}&units=${units}`;
return axios.get(apiUrl).then(getWeatherData);
}
function getWeatherData(response) {
setWeatherdata({
temprature: Math.round(response.data.main.temp),
humidity: response.data.main.humidity,
wind: response.data.wind.speed,
description: response.data.weather[0].description,
city: response.data.name,
country: response.data.sys.country,
});
setLoader(true);
}
if (loader) {
return (
<div>
<div className="row">
<div className="col-md-9">
<Search
data1={searchcity}
onsubmit={(event) => {
onsubmit(event);
}}
data2={value}
onchange={(event) => {
onchange(event);
}}
/>
</div>
<div className="col-md-3 my-auto text-center">
<ShowCurrentLocation
data1={weatherdata.city}
data2={weatherdata.country}
/>
</div>
</div>
<div className="row my-auto">
<div className="col-md-7 my-auto">
<div className="row ">
<div className="col-6 my-auto text-start">
<div>
<HumidityAndWind
data1={weatherdata.humidity}
data2={weatherdata.wind}
/>
</div>
</div>
<div className="col-6 my-auto text-center">
<div>
<ShowCurrentDay />
</div>
</div>
</div>
</div>
<div className="col-md-5 my-auto">
<div className="row">
<div className="col-6 my-auto text-center">
<div>
<CurrentStatus data={weatherdata.description} />
</div>
</div>
<div className="col-6 my-auto text-center">
<CurrentDegree data={weatherdata.temprature} />
</div>
</div>
</div>
</div>
</div>
);
} else {
return "Loader";
}
};
export default Api;
You can't pass data or variable from your children to parent. But you can create some function from parent and pass it into a child that you want and the function is receive parameter for passing your data from children to parent. You can use useState to if you want, and pass that into your children component.
Example using useState:
ParentComponent
import { useState } from "react";
import ChildrenComponent from "./ChildrenComponent";
const ParentComponent = () => {
const [dataFromChild, setDataFromChild] = useState("");
console.log(dataFromChild);
return (
<div>
<ChildrenComponent setDataFromChild={setDataFromChild} />
</div>
);
};
export default ParentComponent;
ChildrenComponent
import { useState } from "react";
const ChildrenComponent = ({ setDataFromChild }) => {
const [data, setData] = useState("");
const handleChange = (e) => {
setData(e.target.value);
};
setDataFromChild(data);
return (
<div>
<label htmlFor="data"></label>
<input type="text" id="data" name="data" onChange={handleChange} />
<span>Its Data: </span>
<span>{data}</span>
</div>
);
};
export default ChildrenComponent;
so in above example we can access data on children component on parent component through function setDataFromChild using useState. Whenever the data onchildren change, the parent dataFromParent should be change to.
Since I am pretty new to react hooks, I am unable to understand some part of the existing code why my component is re-rendering multiple times when the state of an attribute gets changed. Below is the component code. I have added console.log for better understanding.
import React, { useState, useRef } from 'react';
import api from '../api/api';
import { UPLOAD_DATA } from '../api/urls';
import Alert from '../layout/alerts/Alerts';
const StudentDetailsView = ({ symbol }) => {
console.log("inside StudentDetailsView");
const initialState = {
form: {
qualification: symbol.qualification,
profession: symbol.profession
}
};
const [loading, setLoading] = useState(false);
const [errors, setErrors] = useState(null);
const [editFlag, setEditFlag] = useState(false);
const [inputs, setInputs] = useState(initialState);
console.log("before dataUpdated");
const [dataUpdated, setDataUpdated] =useState(false);
console.log("after dataUpdated");
const formRef = useRef(null);
const handleCancel = () => {
setEditFlag(false);
setInputs(initialState);
};
const handleSubmit = (e) => {
console.log("inside handleSumbit");
const form = formRef.current;
e.preventDefault();
e.stopPropagation();
form.classList.add('was-validated');
if (form.checkValidity()) {
callback();
}
};
const callback = ()=> {
setLoading(true);
const formData = new FormData();
formData.append('model', new Blob([JSON.stringify(inputs.form)], {
type: 'application/json'
}));
api.multipartEdit(UPLOAD_DATA, formData)
.then(response => {
setInputs(inputs => ({
...inputs,
form: {
qualification: response.data.qualification,
profession: response.data.profession
}
}));
setErrors(null);
setDataUpdated(true);
})
.catch(error => {
setErrors(error);
})
.finally(() => {
setLoading(false);
setEditFlag(false);
});
}
const handleInputChange = (event) => {
event.persist();
setInputs(inputs => ({
...inputs,
form: {
...inputs.form,
[event.target.name]: event.target.value
}
}));
}
return (
<div>
{
errors &&
<Alert type={errors.type} title={errors.title} description={errors.description} id="alert" />
}
<div >
{editFlag ? (
<div >
</div>
) :
(<div className="edit">
<button type="button" onClick={() => setEditFlag(!editFlag)}>
Edit
</button>
</div>)
}
</div>
<div>
<form className="needs-validation" onSubmit={handleSubmit} ref={formRef} noValidate>
{
editFlag ? (<div className="update-cancel-button">
<button className="btn btn-primary" type="submit" >
{loading ? (
<div className="spinner-border uxf-spinner-border-sm">
<span className="sr-only">Loading...</span>
</div>) : 'Update'}
</button>
<button className="btn btn-secondary cancel-button" type="button" onClick={handleCancel}>Cancel</button>
</div>) : <div></div>
}
<dl className="uxf-dl uxf-dl-horizontal">
<dt>Name</dt>
<dd>{symbol.name}</dd>
<dt>Age</dt>
<dd>{symbol.age}</dd>
<dt>Qualification</dt>
{editFlag ?
(<dd>
<textarea className="form-control" name="qualification" id="qualification"
value={inputs.form.qualification}
onChange={handleInputChange}
maxLength="255"></textarea>
<div className="invalid-feedback">
Please provide a Qualification.
</div>
</dd>)
:
(<dd>{dataUpdated ? (inputs.form.qualification ? inputs.form.qualification : '-') : (symbol.qualification ? symbol.qualification : '-')}</dd>)
}
<dt>Profession</dt>
{editFlag ?
(<dd>
<textarea className="form-control" name="profession" id="profession"
value={inputs.form.profession}
onChange={handleInputChange}
minLength="1"
maxLength="1000"
required></textarea>
<div className="invalid-feedback">
Please provide a Profession.
</div>
</dd>)
:
(<dd>{dataUpdated ? inputs.form.profession : symbol.profession}</dd>)
}
</dl>
</form>
</div>
</div>
);
}
export default StudentDetailsView;
Since my component is getting re-rendered, my state values which are getting set in the code (eg, dataUpdated) are getting updated with the default value again and again. How do I prevent this from happening? Please see the below images for better understanding.
(Showing the mockup of the edit component as the actual data was showing in the actual edit component)
I have clicked the edit button once and then clicked the cancel button once and this is the console log got generated.
Please uase spread operators on initializing or settingup states
const [inputs, setInputs] = useState({...initialState});
const handleCancel = () => {
setEditFlag(false);
setInputs({...initialState});
};