please need your help to more understand this point, what I'm trying to do is to edit the task after posting it adding flag if the task needs to be edited or not with 'edit' flag
always give me the following error You provided a value prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultValue. Otherwise, set either onChange or readOnly
could me to solve that error , please
so App.js:
const App=()=> {
const [tasks,settasks]=useState([])
// const [title,setTitle] = useState('')
const AddHandler=(new_task)=>{
const new_arr = [...tasks,new_task]
settasks(new_arr)
}
const onKeyDownHandler=(event,taskIndex)=>{
if(taskIndex){
console.log('test')
}else{
const new_task = {'title':event.target.value,'edit':false}
if(event.keyCode === 13){
AddHandler(new_task)
}
}
}
const deleteHandler=(taskIndex)=>{
const new_tasks = [...tasks]
new_tasks.splice(taskIndex,1)
settasks(new_tasks)
}
const EditHandler=(editIndex) => {
const new_tasks = [...tasks]
new_tasks[editIndex].edit= true
settasks(new_tasks)
}
return (
<div className={classes.App}>
<h3>To do List ...</h3>
<div className={classes.Form}>
<Input inputtype="text" typing={onKeyDownHandler} />
<Button>Add</Button>
</div>
<Tasks
tasks={tasks}
edit={EditHandler}
typing={onKeyDownHandler}
delete={deleteHandler}/>
</div>
);
}
export default App;
in tasks.js:
const Tasks=(props)=>{
return(
<div>
{props.tasks.map((task,index)=>(
<Task triggeredit={task.edit}
key={index}
index={index}
click={()=>props.delete(index)}
edit={()=>props.edit(index)}
title={task.title}
typing={props.typing}
address={index}
/>
))}
{/*<input onKeyDown={(event)=>props.typing(event,1)}/>*/}
</div>
)
}
export default Tasks
in task.js:
const Task=(props)=>{
return (
<div className={classes.Task}>
<Input inputtype="checkbox" inputstyle='CheckBox'/>
{props.triggeredit ?
<Input
index ={props.index}
inputtype="text"
value={props.title}
typing={props.typing}/>:<p>{props.title}</p>}
<Button click={props.edit}><i className="fa fa-edit"></i></Button>
<Button click={props.click} style="Danger"><i className="fa fa-trash" aria-hidden="true"></i></Button>
</div>
)
}
export default Task
in Input.js:
const Input =(props) => {
let InputHtml = null
switch (props.inputtype) {
case('text'):
InputHtml = <input placeholder="Add Your Tasks"
type="text"
value={props.value}
onKeyDown={(event)=>props.typing(event,props.index)}
className={classes.InputElement}
ref={props.refs}
/>
break
case ('checkbox'):
InputHtml = <input type="checkbox" className={classes.InputElement}/>
break
default:
InputHtml = <input placeholder="Add Your Tasks" type="text" className={classes.InputElement}/>
break
}
return (
<div className={[classes.Input,classes[props.inputstyle]].join(' ')}>
{InputHtml}
</div>
)
}
export default Input
Related
I have a textarea and a button. The button is disabled by default and when the user starts typing, I enable the button to be clicked. But the problem is that, the onClick function is not called while already disabled = false was set.
I've seen this: button onClick doesn't work when disabled=True is initialized (Reactjs)
Seems to be a good idea, but after I setState with the new value, my component is re-rendering, and I don't really want that.
const refText = useRef(null);
const refBtn = useRef(null);
function handleBtnStatus(e) {
let text = e.target.value;
if(text.replace(/\s/g, "").length > 0) {
refBtn.current.disabled = false;
}
else {
refBtn.current.disabled = true;
}
}
function postThis() {
console.log("You posted! Text:", refText.current.value);
// disable again
refBtn.current.disabled = true;
// delete previous text wrote
refText.current.value = "";
}
return (
<>
{isLogged && (
<div className="container">
<div className="content">
<div className="utool-item-text">
<textarea name="textArea" placeholder="Write something.." ref={refText} onChange={(e) => handleBtnStatus(e)}></textarea>
</div>
<div className="utool-item-post">
<button className="ust-btn-post" ref={refBtn} disabled={true} onClick={postThis}>Da Tweet</button>
</div>
</div>
<div className="posts-section">
<div className="list-posts">
{posts.map((p) => {
return (p.hidden === false ? (
<div className="post" key={p.id}>
<div className="post-text">
<span>{p.text}</span>
</div>
</div>
) : (''))
})}
</div>
</div>
</div>
)}
</>
)
Any help?
Use state instead of refs, re-rendering is ok for your case
Simplified example:
import React, { useState } from 'react';
const SimpleExample = () => {
const [textAreaValue, setTextAreaValue] = useState('');
return (
<>
<button disabled={!textAreaValue} onClick={() => console.log('onClick handler')}>
click me
</button>
<textarea value={textAreaValue} onChange={(e) => setTextAreaValue(e.target.value)} />
</>
);
};
And I would recommend checking this Use state or refs in React.js form components?
I know this before but I forgot how did I do it..so basically let say I have
const [showItem,setShowItem] = useState({})
const [updateName,setUpdateName] = useState('')
and then I have a props function that will do something like this...this props is callable for array of items and I want to do this to make it more cleaner and reuseable.
<ItemsEdit items={showItem} setUpdateName_= { setUpdateName } updateName = { updateName } ></ItemsEdit>
Now as you see, when I'm trying to pass my setUpdateName_ and updatename.
UPDATE
This is the map for my items that will call the <ItemsEdit/> for specific id only in my buttons. (but this not affect anything in form)
{nfts.map((nft,i) => {
return(
<div
className="items"
key={nft.id}
>
{showItem.id == nft.id ? <>
<form onSubmit={handleSubmit}>
<ItemsEdit
items={showItem}
setUpdateName= { setUpdateName }
updateName = { updateName }
/>
</form>
</> : <>
<Items items={nft}></Items>
</>}
</div>
)
})}
and here is the <ItemsEdit/>
so for every key that I press it will lose the focus in input but when I used autoFocus = "autoFocus" in the input text it will works but the only thing is that it will the same text in other items..so its not the best idea for me.
const ItemsEdit = ({items,setUpdateName,updateName}) => {
return (
<>
<input
id='name'
type="text"
key="text"
// autoFocus="autoFocus"
value = {updateName}
placeholder="NFT name"
onChange={ e => setUpdateName( e.target.value )}
></input>
<p>{items.id}</p>
<img src={items.data.img} alt="" />
<div className="buttons">
<button
type='submit'>
Update
</button>
<button type='submit' className='left'
onClick={
() => {
setShowItem({})}
}>
<ion-icon name="arrow-back-circle-outline"></ion-icon>
</button>
</div>
</>
)
}
I now have an answer but this kinda nasty for me
so for the <ItemsEdit/> I would call it something like this
{ItemsEdit(
{items:showItem,
setUpdateName:setUpdateName,
updateName:updateName}
)}
and just remove the return of and change the { } into ( )just like this
const ItemsEdit = ({items,setUpdateName,updateName}) => (
)
I'm back once more with something that has been breaking my head today.
so I'm making a contact form is almost done except for an animation I want to include that comes in three steps.
1- prompting the user to contact
2-making the waiting for the user-friendlier with a small loader
3-showing either everything went good and the form was sent or something went wrong
so my idea to accomplish this was to use three different icons/loaders and position all of them on top of each other and make them visible or hide them as necessary using UseState.
for now, I can hide the first icon(from step one) as soon as the submit button is clicked, but I haven't been able to make appear the loader or as the API completes the response the last icon
wondering if I should access it any other way?
import styled from "styled-components";
import { RiMailSendFill,FcApproval } from 'react-icons/all';
import '../../Style/styleComponents/Style.css';
import {sendMessage} from '../../Actions/msgAction';
import { useDispatch, useSelector } from 'react-redux';
import { useForm } from "../../Hook/useForm";
const ContactForm = () => {
const dispatch = useDispatch();
const initFormValues =
{
nombre : "nico ",
email : "sasjaja#asdsa ",
telefono : "asda ",
empresa : "dasd",
mensaje : "dasdas",
date: "s"
}
const[formValues, handleInputChange, reset] = useForm(initFormValues);
const{nombre, email, telefono, empresa, mensaje} = formValues
//loader submit buttons
const[mail, setMail]= useState(true);
const[loading, setLoading]= useState(false);
const[approved, setApproved]= useState(false);
const handleSendMsg = ( event ) =>
{
event.preventDefault();
dispatch( sendMessage( formValues ) )
.then( ( result ) =>
{
if( result )
{
console.log(initFormValues);
//closeModal();
console.log('dat')
};
setLoading(true);
});
reset();
}
const showE =()=> {
if (mail) {
setMail(false)
setLoading(true)
console.log("pressed submit");
}
}
const showL=()=>{
if (loading) {
setLoading(false)
console.log("sending email ");
}
}
return (
<Container>
<Left>
<h1>Tráenos tus desafíos</h1>
</Left>
<Right>
<form onSubmit={ handleSendMsg }>
<Label>
<Linput>
<Name>
<label htmlFor="name">Nombre:</label>
<input type="text" id="name" required name="nombre" value={ nombre } onChange={ handleInputChange } />
</Name>
<Tel>
<label htmlFor="name">Telefono:</label>
<input type="text" id="phone" required name="telefono" value={ telefono } onChange={ handleInputChange } />
</Tel>
<Company>
<label htmlFor="company">Empresa:</label>
<input type="text" id="company" name="empresa" value={ empresa} onChange={ handleInputChange }/>
</Company>
</Linput>
<Rinput>
<Email>
<label htmlFor="email">E-mail:</label>
<input type="email" id="email" required name="email" value={ email } onChange={ handleInputChange }/>
</Email>
<Msg>
<label htmlFor="message">Mensaje:</label>
<textarea id="message" required name="mensaje" rows="8" cols="50" value={ mensaje } className="bigger" onChange={ handleInputChange }/>
</Msg>
</Rinput>
</Label>
<Button>
<Send>
<button type="Submit" id ="submit" onClick={showE, showL}>Enviar</button>
</Send>
<Sent>
<RiMailSendFill id="mail" className={ mail ? 'svg': "svg active"}/>
<Loader className={ loading ? 'spin': "spin active"}>
<div class="spin"></div>
</Loader>
{/* <FcApproval id= "approve" className={ approved ? 'approve': "approve active"}/> */}
</Sent>
</Button>
</form>
</Right>
</Container>
);
};
export default ContactForm;
thanks, yall always saving me!
There are ways to make states work with each other easiest way is like this.
1-useStates for each of the
elements you want to be able to switch states to.
const [mail, setMail] = useState(true);
const [approved, setApproved] = useState(false);
2 Main function with smaller functions,
for each one to change accordingly.
function showL( ){
setMail(false);
if(!mail){
return setApproved(true);
}
}
//hide mailIcon / show approve
function showA( ){
setApproved(true);
if(approved){
return setMail(false);
}
}
add an event listener to the specific
the element you will work with to trigger the changes,
here you pass the two functions like this.
<Button>
<Send>
<button type="Submit" id="submit" onClick={() => {showL(); showA();}}>
Enviar
</button>
</Send>
TERNARY EXPRESION if true, render element and false null
<Sent>
<EMail>
{mail ? <RiMailSendFill/> : null}
</EMail>
<Loader>
{approved ? <FcApproval/>: null}
</Loader>
</Sent>
</Button>```
I already built the form in React and it shows the input fields in red borders that'll change to regular borders once someone types it in. I used this example from this React form article link So everything is working except I wanted to add the error message under the input field that displays "Please fill in the blank field" that will disappear once someone starts typing in the field. How do I do this?
Here's my code in Form.js:
import React, { Component } from 'react';
import FormField from './FormFieldBox';
function validate(name, isin) {
// true means invalid, so our conditions got reversed
return {
name: name.length === 0,
isin: isin.length === 0
};
}
export default class PopupForm extends Component {
constructor(props) {
super(props)
this.state = {
name: '',
isin: '',
country: '',
errormessage: ''
}
}
updateInput = (e) =>{
this.setState({[e.target.name]: e.target.value})
}
closePopupSubmit = (e) => {
if (!this.canBeSubmitted()) {
e.preventDefault();
}
let security = { //1.gather security data from form submit
name: this.state.name,
isin: this.state.isin,
country: this.state.country
}
this.props.submitPopup(security); //2.closePopup function, add security data
}
canBeSubmitted() {
const errors = validate(this.state.name, this.state.isin);
const isDisabled = Object.keys(errors).some(x => errors[x]);
return !isDisabled;
}
cancelPopupSubmit = (e) => {
e.preventDefault()
this.props.cancelPopup();
}
render() {
const errors = validate(this.state.name, this.state.isin);
const isDisabled = Object.keys(errors).some(x => errors[x]);
return (
<div className='popup'>
<div className='popup-inner'>
<form onSubmit={this.closePopupSubmit}>
<FormField onChange={this.updateInput} className={errors.name ? "input error" : "input"} label="Name" type="text" name="name" value={this.state.name} />
<FormField onChange={this.updateInput} className={errors.isin ? "input error" : "input"} label="ISIN" type="text" name="isin" value={this.state.isin} />
<FormField onChange={this.updateInput} label="Country" type="text" name="country" value={this.state.country} />
<button type="button" onClick={this.cancelPopupSubmit} className="button">Cancel</button>
<button type="submit" className="button" disabled={isDisabled}>Submit</button>
</form>
</div>
</div>
)
}
}
And my component FormField.js
import React from "react";
const FormBox = props => {
return (
<div className="field">
<label className="label">{props.label}</label>
<div className="control">
<input onChange={props.onChange}
className={props.className}
type={props.type}
name={props.name}
value={props.value}
placeholder={props.placeholder} />
{/* {props.errormessage} */}
</div>
</div>
)
}
export default FormBox;
const FormBox = props => {
return (
<div className="field">
<label className="label">{props.label}</label>
<div className="control">
<input onChange={props.onChange}
className={props.className}
type={props.type}
name={props.name}
value={props.value}
placeholder={props.placeholder} />
</div>
{Boolean(props.value.length) || (
<div className="err-msg">
Please fill in the blank field
</div>
)}
</div>
)
}
There are two ways you can achieve this
First : oninvalid attribute in HTML5 and calling a custom function on that.
Second : along with each element name object in state have a length attribute. In validation function you can check for the length and throw a custom error that you want to display.
I have this checkbox component!
const CheckBox = props =>{
var [show,setshow] = useState(false);
const option = props.name.replace(/\s/g, '');
return(
<div className="filter-option" onClick={e=>setshow(!show)} data={option}>
<div className={show?"check-bock checked":"check-bock"} >
<i className="fa fa-check"></i>
</div>
<label className="font-20">{props.name}</label>
</div>
)
}
The checked class will show checkmark, but if i want to render multiple checkboxes the problem is all checkboxes are checked at once!
I want only one checked and others unchecked!
The solution is to keep in state which checkbox is checked and store this state in parent from where all checkboxes are rendered
const CheckBox = props =>{
const option = props.name.replace(/\s/g, '');
return(
<div className="filter-option" onClick={e=>props.setshow(prev => props.name == prev? '': props.name)} data={option}>
<div className={props.show?"check-bock checked":"check-bock"} >
<i className="fa fa-check"></i>
</div>
<label className="font-20">{props.name}</label>
</div>
)
}
const Parent = () => {
var [show,setshow] = useState('');
return (
<>
<Checkbox name="first" show={"first" === show} setShow={setShow}/>
<Checkbox name="second" show={"second" === show} setShow={setShow}/>
</>
)
}