useState to receive input data and post to console - reactjs

Still a junior with React and I'm trying to detect an input from the front end and use useState to collect the input data and post it through the console. I followed React's own tutorial but I can't get this right. It's probably something small I'm forgetting but I've been stuck on this for days. Please help.
function Cards2() {
const [input, setInput] = useState();
console.log(input);
return (
<div id="cards" style={{width: 'auto', margin: '10px'}}>
<div className="card-header" id="card-header" style={{backgroundColor: 'dimgray', color: 'white'}}>
<h5>Header</h5>
</div>
<div className="card-body" id="card-body" style={{backgroundColor: 'lightgrey'}}>
<blockquote className="blockquote mb-0">
<p>Enter Name:</p>
<input onChange={() => setInput(input)} type="email" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"/>
<button type="submit" className="btn btn-primary" style={{marginTop: '7px'}}> Submit </button>
<footer className="blockquote-footer">
Someone famous in <cite title="Source Title">Source Title</cite>
</footer>
</blockquote>
</div>
</div>
);
}
export default Cards2;

Your onChange handler in Input needs to be like this:
<input onChange={(event) => setInput(event.target.value)} type="email" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"/>
You can use useEffect as suggested in previous answer but that doesn't really matter.

You'll need to use useEffect to track any changes to the input value (or any state value, for that matter). The following link also explains how useEffect works, and how to work it with input.
https://daveceddia.com/useeffect-hook-examples/
import React, { useState, useEffect } from 'react';
function Cards2() {
const [input, setInput] = useState();
useEffect(() => {
console.log(input);
}, [input]);
return (
// your code here
);
}
export default Cards2;

Related

Reactjs input tag causing the whole page to not load

So, I was learning React Hooks and everything was going fine until the tag was added as I normally would add it like this: , however, this caused the whole page to collapse but writing it in this way, or react usual way to witting tags made it work again. any explanation behind this?
import React from 'react'
import { useState } from 'react'
function CounterHook() {
const [count, Setcount] = useState(0)
let [text, set_text] = useState("This is a Test TEXT")
let [info , set_info] = useState({name:'', email:''})
return (
<div>
<h3>{count}</h3>
<button onClick={() => Setcount(count + 1)} className='btn btn-primary'> Click </button>
<h3> {text} </h3>
<button onClick={()=> set_text("The test Text has change nothing is the same anymore ")}
className='btn btn-success'> Change Me </button>
<br />
<br />
<form>
<input type="text" className={'form-control'} value={info.name}
onChange={ event => set_info({name: event.target.value})} /> Enter your Name
<input type={'text'} className={'form-control'} value={info.email}
onChange={ event => set_info({email: event.target.value})} /> Enter your Email
{/* COMMENTED OUT CODE */} {/* that part of the code made the whole page blank */}
{/* <input type="text" className={'form-control'} value={info.name}
onChange={ event => set_info({name: event.target.value})}> Enter your Name </input>
<input type={'text'} className={'form-control'} value={info.email}
onChange={ event => set_info({email: event.target.value})}> Enter your Email </input> */}
<h2> Name is: {info.name} </h2>
<h2> Email is : {info.email} </h2>
</form>
</div>
)
}
export default CounterHook
So one problem that immediately jumps out at me is that info is supposed to be an object with the shape: {name:'', email:''} but you are setting it to {name:''} or {email:''} which will cause the object to be missing one of the object props. You are then trying to reference both props in which one of them will be undefined depending on what input you type in. Try having a two separate states for each of the values like so:
const [name, setName] = useState('');
const [email, setEmail] = useState('');
Alternatively you could try in your onChange event something like this:
This is for the name input event handler
(event)=> set_info(previousState=> {name:event.target.value, email:previousState.email})
I haven't tested option 2 but in theory it should work. Hope this helps.

How to add no of fields dynamically by taking input from user react

I want to add the input no of fields given by the user when clicking on submit button.How to do this in react functional component.
screenshot:
I have an input field,when any user input on that field and submit,according to the input given by the user the no fields will be created.like in above screenshot if a user gives input 6 then 6 fields will be added
I am trying in this way,
import React, { useState } from 'react'
import cal from './image/bgimg.jpg'
function Home() {
const [state,setState]=useState({
semester:'',
credit:'',
sgpa:''
})
const [noOfSem,setNoOfSem]=useState()
const handleChange=(e)=>{
setState({...state,[e.target.name]:e.target.value})
}
const handleClick=()=>{
console.log('hyy',state.semester)
setNoOfSem([state.semester])
}
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<img src={cal} alt="" className='imgcal img-fluid' />
</div>
<div className="col-md-6">
<div className="col-md">
<div className="form1">
<input type="number" value={state.semester} name='semester' onChange={handleChange} placeholder='Enter Total Semester' />
<button type="button" class="btn btn-success" onClick={handleClick}>Submit</button>
<div className="form2">
{noOfSem?.map((item,index)=>
<>
<input type="text" placeholder={`Enter your Semester ${index+1} credit`} key={index}/>
</>
)}
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default Home
thanks......
I think there's a few changes you can make to improve the code and get it working.
Firstly, I would avoid storing your number of semesters in both the state.semester and noOfSem state, as it means you have to update both of them to keep them in sync.
Given that your component only needs to know the number of semesters when the user presses Submit, you can remove the handleChangeCall and instead only access the value upon submit.
It is also good practice to make use of the <form onSubmit={}> and <input type='submit'> elements, to handle form submission. Instead of using the onClick event from a regular <button>. Some info here.
When using the form, you can then access the value of the semester input directly by storing a reference to it using useRef.
Then in order to iterate over the number of semester, you can construct a new Array to map over. One caveat here is that you have to call the array fill method.
See solution here:
import React, { useState, useRef } from "react";
function Home() {
const [state, setState] = useState({
semester: '',
credit: "",
sgpa: ""
});
const semesterInputRef = useRef();
const handleForm1Submit = (e) => {
e.preventDefault();
if (semesterInputRef?.current.value) {
setState({ ...state, semester: Number(semesterInputRef.current.value) });
}
};
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<div className="col-md">
<form className="form1" onSubmit={handleForm1Submit}>
<input
type="number"
name="semester"
ref={semesterInputRef}
placeholder="Enter Total Semester"
></input>
<input type="submit" className="btn btn-success"></input>
</form>
<form className="form2">
{state.semester &&
Array(state.semester).fill().map((_item, index) => (
<input
key={index}
type="text"
placeholder={`Enter your Semester ${index + 1} credit`}
></input>
))}
</form>
</div>
</div>
</div>
</div>
);
}
export default Home;
I've also created a code sandbox to show that this works as expected, here.

Trying to get a innerhtml functionality to work in react todo list

I am aiming for new tasks to show as user clicks "add task", simple I know, but still learning react.
My goal was to use a ternary operator until its no longer null, and then map through the array each time a user clicks add task.
Issue:
I believe the renderTasks array isn't set by the time it tries to map over it, I get an error...
renderTasks.map is not a function
Is there a way I could utilize the useEffect for what I am trying to do, or any better ideas that could help? Thanks
Here's the code snippet of App.js
function App() {
const [tasks, setTasks] = useState([]);
const [renderTasks, setRenderTasks] = useState(null);
const handleAddTask = () => {
setRenderTasks(tasks);
};
const handleOnChange = (e) => {
setTasks({
...tasks,
[e.target.name]: e.target.value,
});
};
return (
<>
<div className="overview">
<label className="my-todos">My Todos</label>
<div className="input-div">
<div className="input-container">
<label className="title-desc">Title</label>
<input
name="title"
onChange={handleOnChange}
className="input-values"
type="text"
></input>
</div>
<div className="input-container">
<label className="title-desc">Description</label>
<input
name="description"
onChange={handleOnChange}
className="input-values"
type="text"
></input>
</div>
<button onClick={handleAddTask} className="add-task">
Add Task
</button>
</div>
{renderTasks !== null ? (
<ul>
{renderTasks.map((x) => {
return <li>{x.title - x.description}</li>;
})}
</ul>
) : null}
</div>
</>
);
}
export default App;
There were few issues in your implementation like how you destructing tasks, trying to access an object as an array and abusing the useState. You don't need useEffect or two useState to do the trick.
import React from "react";
import React, { useState } from 'react';
import "./style.css";
function App() {
const [tasks, setTasks] = useState([]);
const task = {};
const handleOnChange = (e) => {
task[e.target.name] = e.target.value;
};
const onClickHandler = (e)=>{
(task.title) && setTasks( [...tasks, task]);
}
return (
<>
<div className="overview">
<label className="my-todos">My Todos</label>
<div className="input-div">
<div className="input-container">
<label className="title-desc">Title</label>
<input
name="title"
onChange={handleOnChange}
className="input-values"
type="text"
></input>
</div>
<div className="input-container">
<label className="title-desc">Description</label>
<input
name="description"
onChange={handleOnChange}
className="input-values"
type="text"
></input>
</div>
<button onClick={onClickHandler} className="add-task">
Add Task
</button>
</div>
<ul>
{tasks.map((x) => {return <li>{x.title} - {x.description}</li> })}
</ul>
</div>
</>
);
}
export default App;
Even though you are initialising tasks to be an array, in handleOnChange you are setting it to an Object like this -
setTasks({
...tasks,
[e.target.name]: e.target.value,
});
This same tasks object you are trying to set for renderTasks in handleAddTask. So renderTasks is assigned to an Object and not an array and only arrays have map function and hence you are facing the issue renderTasks.map is not a function error
Try doing
Object.keys(renderTasks).map((x) => {
return <li>{x.title - x.description}</li>;
})

Clear form after submit React

In my app, I am making a form to add animal for adoption with React. The data is stored in Mongo if this is important to know.
But I can not figure out how, I tried to look and nothing works for me. Maybe there is something wrong with the form. I would be very thankful if someone can tell me how to clear or reset the form after submitting. I simplified it so it would be easy to see what I have. Here is my form:
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { addAnimal } from "../redux/actions";
const AddAnimalForm = () => {
const dispatch = useDispatch();
const [name, setName] = useState("");
const [kind, setKind] = useState("");
const [displayForm, setDisplayForm] = useState(false);
const dispatchAddAnimal = () => {
dispatch(
addAnimal(
{
name,
kind
},
"_id name kind sex age city author phone info"
)
);
};
const onShowButtonClicked = () => {
setDisplayForm(true);
};
const onHideButtonClicked = () => {
setDisplayForm(false);
};
return !displayForm ? (
<button className="col-xs-12 col-md-3" onClick={onShowButtonClicked}>
add
</button>
) : (
<React.Fragment>
<div className="col-xs-12 col-sm-9">
<button className="col-xs-12 col-md-3" onClick={onHideButtonClicked}>
hide{" "}
</button>
<form>
<div className="form-row">
<div className="form-group col-md-6">
<label htmlFor="animal-name">name</label>
<input
type="text"
className="form-control"
onChange={e => setName(e.target.value)}
id="animal-name"
/>
</div>
<div className="form-group col-md-6">
<label htmlFor="kind">kind</label>
<input
type="text"
onChange={e => setKind(e.target.value)}
className="form-control"
id="kind"
/>
</div>
</div>
<button
type="button"
className="btn btn-primary"
onClick={dispatchAddAnimal}
>
add animal
</button>
</form>
</div>
</React.Fragment>
);
};
export default AddAnimalForm;
define a variable at the top just below you imports
let exampleRef = React.createRef()
hi first you have to create a reference to that form like this :-
<form ref={(el) => myFormRef = el;}>
<input />
<input />
...
<input />
</form>
and after that, while submitting your form you just use the reset() method provided by the form reference like this
const dispatchAddAnimal = () => {
myFormRef.reset();
dispatch(
addAnimal(
{
name,
kind
},
"_id name kind sex age city author phone info"
)
);
};
let me know if it works for you or not.
there is also a great library React Advanced Form which handle lots of thing on its own like validation and other stuff check this out if you feel free

'Input' is not defined react/jsx-no-undef, what does that mean?

Im trying to make an input field for name in my code, and I get:
'Input' is not defined react/jsx-no-undef and I cant see whats wrong, can anyone please help me?
I will later pass name into my dispatch
The form part with textarea is working.
import React, { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import '../styles/NewMessage.css'
import { fetchNewMessage } from 'reducer/messages'
export const NewMessage = () => {
const [message, setMessage] = useState('')
const [name, setName] = useState('')
const dispatch = useDispatch()
const handleMessageSubmit = (event) => {
event.preventDefault()
//console.log('addNewMessage', message)
dispatch(fetchNewMessage(message))
setMessage('')
}
return (
<div className="add-message-container">
{/* ******Form for sending a new message******* */}
<form onSubmit={handleMessageSubmit} className="add-message-form">
<span>
<label>
Name:
This input is giving me the 'Input' is not defined react/jsx-no-undef
<Input
placeholder="Name"
type="text"
onChange={event => setName(event.target.value)}
value={name}
required
/>
</label>
</span>
This textarea is working fine
<span>
<label For="new-message">
<textarea
id="new-message"
className="input-message"
rows='3'
minLength='5'
maxLength='150'
placeholder="Type your message"
onChange={(event) => setMessage(event.target.value)}
value={message}
required />
</label>
</span>
{/* * Form submit button * */}
<div className="add-message-btn-container">
<button
className="add-message-btn"
type="submit"
title="Send">
Send
</button>
</div>
</form>
</div>
)
}
You either need to import Input component from some component library or you need to use input which is the HTML element. JSX tags are case-sensitive, which is why it gives you are warning from eslint
<input
placeholder="Name"
type="text"
onChange={event => setName(event.target.value)}
value={name}
required
/>
it is <input> tag with small i.
Use <input /> instead of <Input />, as JSX attributes are case-sensitive

Resources