I created a simple to do list wherein the add and delete works. My problem is, after submitting a todo, the input box won't clear.
This is my app.js
const App = () => {
const [toDoList, setToDoList] = useState([]);
const [toDo, setToDo] = useState("");
const handleToDo = (event) => {
const { value } = event.target;
setToDo(value);
};
const submit = () => {
//const list = toDoList;
const newItem = {
id: 1 + Math.random(),
value: toDo,
};
if (newItem.value && !toDoList.includes(newItem.value)) {
toDoList.push(newItem);
setToDoList([...toDoList]);
}
};
return (
<div className="container">
Add an Item
<br />
<input
type="text"
placeholder="Type item here..."
onChange={handleToDo}
/>
<button className="add-btn btn-floating" onClick={submit}>
<i class="material-icons"> + </i>
</button>
<br />
<ul>
...display of todos here
</ul>
</div>
);
//}
};
export default App;
I'm confused as to where I should insert the useState so that the input would be reset.
The value of the input box must also be governed by the state. So the input should be like:
<input
value={toDo}
type="text"
placeholder="Type item here..."
onChange={handleToDo}
/>
Once You click on submit, reset the toDo to empty
const submit = () => {
//const list = toDoList;
const newItem = {
id: 1 + Math.random(),
value: toDo,
};
if (newItem.value && !toDoList.includes(newItem.value)) {
toDoList.push(newItem);
setToDoList([...toDoList]);
}
setToDo("");
};
Your input seems to be half-controlled. You should also give the input a value property as such:
<input
type="text"
placeholder="Type item here..."
onChange={handleToDo}
value={toDo}
/>
And now you can clear out the input when a task is submitted:
const submit = () => {
//rest of the code here...
setToDo('') //this'll clear out the value of your input
};
You can add a value to input element. And after submit, set it to an empty string. So:
const App = () => {
const [toDoList, setToDoList] = useState([]);
const [toDo, setToDo] = useState("");
const handleToDo = (event) => {
const { value } = event.target;
setToDo(value);
};
const submit = () => {
//const list = toDoList;
const newItem = {
id: 1 + Math.random(),
value: toDo,
};
if (newItem.value && !toDoList.includes(newItem.value)) {
toDoList.push(newItem);
setToDoList([...toDoList]);
setToDo("");
}
};
return (
<div className="container">
Add an Item
<br />
<input
type="text"
value={toDo}
placeholder="Type item here..."
onChange={handleToDo}
/>
<button className="add-btn btn-floating" onClick={submit}>
<i class="material-icons"> + </i>
</button>
<br />
<ul>
{toDoList.map((todoLi) => (
<li>{todoLi}</li>
))}
</ul>
</div>
);
//}
};
export default App;
You just have to pass empty string in setToDo, after all the code in your submit function setToDo("")
Related
I have 2 arrays that I used the map() function to add to an array, but the problem I'm having is they are being grouped by name and grouped by review but I want them to return name + review independently of each other when I click submit on my form. Here's an example of what's happening:
I want it so David's review ("great movie") is separate from Daniel's review ("my favorite").
I've tried all sorts of things to no avail. Here is my code:
import { Button, Form, Input } from "reactstrap";
import Stars from "./stars";
export default function ReviewForm() {
const [reviewinput, setReviewInput] = useState("");
const [reviewarray, setReviewArray] = useState([]);
const [nameinput, setNameInput] = useState("");
const [namearray, setNameArray] = useState([])
const [starinput, setStarInput] = useState();
const [stararr, setStarArr] = useState(0)
const onChange = (e) => {
setReviewInput(e.target.value);
};
const onChangeName = (e) => {
setNameInput(e.target.value);
};
const onSubmit = (e) => {
e.preventDefault();
console.log('submitted');
if (reviewinput) {
reviewarray.push(reviewinput);
setReviewArray(reviewarray);
}
if (nameinput) {
namearray.push(nameinput);
setNameArray(namearray);
}
if (starinput) {
stararr.push(starinput);
setStarArr(stararr);
}
setReviewInput('');
setNameInput('');
setStarInput(0)
};
console.log(reviewarray);
return (
<div className="form-container">
<Stars setStar={setStarArr} />
<Form onSubmit={onSubmit}>
<Input
className="form-control" type="text"
placeholder="Enter your name"
value={nameinput}
onChange={onChangeName}
/>
<Input
className="form-control"
type="textarea"
placeholder="Enter your review"
value={reviewinput}
onChange={onChange}
/>
<br></br>
<Button type="submit" className="btn btn-primary">
Submit
</Button>
<br></br>
<br></br>
<div className="card-header border boorder-dark">
<h5>Reviews</h5>
</div>
<div className="card-body border border-secondary">
{namearray.map((name, i) => <p key={i}>{name}</p>)}
<br></br>
{reviewarray.map((review, i) => <p key={i}>{review}</p>)}
<p>I rate it this movie {stararr} stars!</p>
</div>
</Form>
</div>
);
}
// STAR COMPONENT \\
import React, { useState } from "react";
import { FaStar} from 'react-icons/fa'
const Stars = ({ setStar }) => {
const [rating, setRating] = useState(0);
const [hover, setHover] = useState(null);
const handleClick = (ratingValue) => {
setRating(ratingValue);
setStar(ratingValue);
};
return (
<div>
{[...Array(5)].map((star, i) => {
const ratingValue = i + 1;
return (
<label key={i}>
<input
type="radio"
name="rating"
value={ratingValue}
onClick={() => handleClick(ratingValue)}
/>
<FaStar
className="star"
color={ratingValue <= (hover || rating) ? "gold" : "lightgray"}
size={20}
onMouseEnter={() => setHover(ratingValue)}
onMouseLeave={() => setHover(null)}
/>
</label>
);
})}
<p>I rate this movie {rating + " stars"}</p>
</div>
);
};
export default Stars;```
It would be simpler to do this using an object instead of combining two arrays.
Make each review an object that contains a review, name, and your stars like so:
{
name: 'a',
review: 'good',
stars: 5
}
This way you could just use one array and push that object instead.
The reason your stars wasn't updating to 0 is because in your ./stars file you made a new stars state when you could have just re-used the one from your main component. Other than that, your code was fine.
updated code:
main file
import React, { useState } from "react";
import { Button, Form, Input } from "reactstrap";
import Stars from "./stars";
export default function ReviewForm() {
const [reviewinput, setReviewInput] = useState("");
const [reviewarray, setReviewArray] = useState([]);
const [nameinput, setNameInput] = useState("");
const [stararr, setStarArr] = useState(0);
const onChange = (e) => {
setReviewInput(e.target.value);
};
const onChangeName = (e) => {
setNameInput(e.target.value);
};
const onSubmit = (e) => {
e.preventDefault();
console.log("submitted");
const review = {};
if (reviewinput) {
review.review = reviewinput;
}
if (nameinput) {
review.name = nameinput;
}
review.stars = stararr;
setReviewArray([...reviewarray, review]);
setReviewInput("");
setNameInput("");
setStarArr(0);
const form = e.target
form.reset() /* to reset radio buttons to initial */
};
console.log(reviewarray);
return (
<div className="form-container">
<Form onSubmit={onSubmit}>
<Stars setStar={setStarArr} stararr={stararr} />
<Input
className="form-control"
type="text"
placeholder="Enter your name"
value={nameinput}
onChange={onChangeName}
required
/>
<Input
className="form-control"
type="textarea"
placeholder="Enter your review"
value={reviewinput}
onChange={onChange}
required
/>
<br></br>
<Button type="submit" className="btn btn-primary">
Submit
</Button>
<br></br>
<br></br>
<div className="card-header border boorder-dark">
<h5>Reviews</h5>
</div>
<div className="card-body border border-secondary">
<br></br>
{reviewarray.map(({ review, name, stars }, i) => (
<div key={i}>
<p>name: {name}</p>
<p>review: {review}</p>
<p>stars: {stars}</p>
</div>
))}
<p>I rate it this movie {stararr} stars!</p>
</div>
</Form>
</div>
);
}
star component
import React, { useState } from "react";
import { FaStar } from "react-icons/fa";
const Stars = ({ setStar, stararr }) => {
const [hover, setHover] = useState(null);
const handleClick = (ratingValue) => {
setStar(ratingValue);
};
return (
<div>
{[...Array(5)].map((star, i) => {
const stararr = i + 1;
return (
<label key={i}>
<input
type="radio"
name="rating"
value={stararr}
onClick={() => handleClick(stararr)}
/>
<FaStar
className="star"
color={stararr <= (hover || stararr) ? "gold" : "lightgray"}
size={20}
onMouseEnter={() => setHover(stararr)}
onMouseLeave={() => setHover(null)}
/>
</label>
);
})}
<p>I rate this movie {stararr + " stars"}</p>
</div>
);
};
export default Stars;
Edit: To incorporate the stars input as well
For your stars component I just replaced wherever you had ratings to your original stars value.
Like Bas bas told you, I think it's better to combine the name and the review in the same item in the reviews array.
I also wrote it a bit shorter and understandable:
import { Button, Form, Input } from "reactstrap";
import Stars from "./stars";
export default function ReviewForm() {
const [nameInput, setNameInput] = useState("");
const [reviewInput, setReviewInput] = useState("");
const [starInput, setStarInput] = useState(0);
const [reviews, setReviews] = useState([]);
const onSubmit = (e) => {
e.preventDefault();
if (!nameInput || !nameInput.length || !reviewInput || !reviewInput.length || isNaN(starInput)) {
return;
}
setReviews((prev) => [
...prev,
{
name: nameInput,
review: reviewInput,
rating: starInput
}
]);
clearForm();
};
const clearForm = () => {
setNameInput('');
setReviewInput('');
setStarInput(0);
};
return (
<div className="form-container">
<Stars setStar={setStarInput} />
<Form onSubmit={onSubmit}>
<Input
className="form-control" type="text"
placeholder="Enter your name"
value={nameInput}
onChange={(e) => setNameInput(e.target.value)}
/>
<Input
className="form-control"
type="textarea"
placeholder="Enter your review"
value={reviewInput}
onChange={(e) => setReviewInput(e.target.value)}
/>
<br></br>
<Button type="submit" className="btn btn-primary">
Submit
</Button>
<br></br>
<br></br>
<div className="card-header border boorder-dark">
<h5>Reviews</h5>
</div>
<div className="card-body border border-secondary">
{reviews.map(({ name, review }, i) =>
<p key={i}>{name} - {review}</p>
)}
</div>
</Form>
</div>
);
}
There are many options to achieve this. What you want to do is to zip() (at least Python developers would use this term), so that means you want to group together the first, second, third, ... element of the two given arrays. Then you could map() over the resulting array and display the values as you please.
For your example you could just use something like the following using map():
const names = ["Thomas", "Peter", "Tom", "Mark", "John"];
const reviews = [
"Well, this was shit.",
"Love me some sharks",
"Sharknadoooo!",
"It's a terrible joy.",
"I've seen a peanut stand, I've heard a rubber band, I've seen a needle wink it's eye, but I ain't never seen a Shark fly",
];
const result = names.map((name, idx) => ({ name: name, review: reviews[idx] }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
In a more general sense with any number of arrays you could use a generator function although you could do it without one. But this is a quite convenient and simple way to achieve what you want which generates the values as you need them when using for ... of.
const names = ["Thomas", "Peter", "Tom", "Mark", "John"]
const reviews = ["Well, this was shit.", "Love me some sharks", "Sharknadoooo!", "It's a terrible joy.", "I've seen a peanut stand, I've heard a rubber band, I've seen a needle wink it's eye, but I ain't never seen a Shark fly"]
/**
* Zips any number of arrays. It will always zip() the largest array returning undefined for shorter arrays.
* #param {...Array<any>} arrays
*/
function* zip(...arrays){
const maxLength = arrays.reduce((max, curIterable) => curIterable.length > max ? curIterable.length: max, 0);
for (let i = 0; i < maxLength; i++) {
yield arrays.map(array => array[i]);
}
}
// put them in a array
const test = [...zip(names, reviews)]
console.log(test);
// or lazy generate the values
for (const [name, review] of zip(names, reviews)) {
console.log(`${name}: ${review}`);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
function Input() {
const [input, setInput] = useState("");
function handleSearch() {
let url = "https://google.com/search?q=${input}"
window.open(url)
}
return (
<div className="input-wrap">
<input
type="text"
className="input__search"
placeholder="Enter your search..."
value={input}
onChange={(e) => setInput(e.target.value)}></input>
<button
className="input__search--btn"
onClick={handleSearch}>
<i className="fa-solid fa-magnifying-glass"></i>
</button>
</div>
);
}
The search button when clicked will redirect you to a google search based on the value from the input field, below is the site for advanced search, when active the link will add an additional link after "https://google.com/search?q=${input}+site%3A${activepage}.com, how do I check if one or many sites are active then pass down its name to url
P/s: code for toggling websites
function WebButton({ icon, name }) {
const [active, setActive] = useState(false);
function handleToggle() {
setActive(!active);
}
return (
<button
className={active ? "websites-btn active" : "websites-btn"}
onClick={handleToggle}>
<i className={icon}></i>
<div className="websites-name">{name}</div>
</button>
);
}
You can keep a root level state to gather active links to a state. And pass it to the Input component.
Update your Input component to accept array called `` and update the handleSearch to use OR operation in google search.
function Input({ activeLinks }) {
const [input, setInput] = useState("");
function handleSearch() {
if (activeLinks.length > 0) {
let compundSearchURL = `https://google.com/search?q=${input}`;
activeLinks.forEach((link, i) => {
compundSearchURL += `+${i > 0 ? "OR+" : ""}site%3A${link}.com`;
});
window.open(compundSearchURL);
} else {
window.open(`https://google.com/search?q=${input}`);
}
}
return (
<div className="input-wrap">
<input
type="text"
className="input__search"
placeholder="Enter your search..."
value={input}
onChange={(e) => setInput(e.target.value)}
></input>
<button className="input__search--btn" onClick={handleSearch}>
<i className="fa-solid fa-magnifying-glass">Search</i>
</button>
</div>
);
}
Accept another function in WebButton called toggleActiveLink and a string called value which refers to the URL part. Call the function with the value inside handleToggle function.
function WebButton({ icon, name, toggleActiveLink, value }) {
const [active, setActive] = useState(false);
function handleToggle() {
setActive(!active);
toggleActiveLink(value);
}
return (
<button
className={active ? "websites-btn active" : "websites-btn"}
style={{ color: active ? "blue" : "unset" }}
onClick={handleToggle}
>
<i className={icon}></i>
<div className="websites-name">{name}</div>
</button>
);
}
In the main component you have to create a local state to handle the active links. Create the toggle function as given. It will add the value if it is not there otherwise remove it.
const urls = [
{ name: "Reddit", value: "reddit" },
{ name: "Quora", value: "quara" },
{ name: "Facebook", value: "facebook" },
{ name: "Stackoverflow", value: "stackoverflow" },
{ name: "Twitter", value: "twitter" }
];
function App() {
const [activeLinks, setActiveLinks] = useState([]);
const toggleActiveLink = (link) => {
const index = activeLinks.indexOf(link);
if (index < 0) {
setActiveLinks((prevLinks) => [...prevLinks, link]);
} else {
setActiveLinks((prevLinks) => prevLinks.filter((l) => l !== link));
}
};
return (
<>
<Input activeLinks={activeLinks} />
<div>
{urls.map(({ name, value }) => (
<WebButton
name={name}
value={value}
toggleActiveLink={toggleActiveLink}
/>
))}
</div>
</>
);
}
I want to get the value when I change it with onChange and created a name and contact number by using the value and setContacts, this app does not cause error but it does not work, Where is the problem? Thanks.
Each new contact in an object has an id, a name and a phone number
const AddUSer = () => {
const {contacts, setcontacts}=useState([]);
const { userName, setUSerName } = useState("");
const { userPhone, setUserPhone } = useState("");
const setName = (e) => {
const value = e.target.value;
return setUSerName(value);
};
const setPhone = (e) => {
const value = e.target.value;
return setUserPhone(value);
};
const handleNewcontact = () => {
const allcontacts = [...contacts];
const newContact = {
id: Math.floor(Math.random() * 1000),
fullName: userName,
phone: userPhone,
};
allcontacts.push(newContact);
setcontacts(allcontacts);
setUSerName("");
setUserPhone("");
}
};
return (
<div className="container">
<form>
<label>Name</label>
<input className="form-control" onChange={(e) => setName} />
<label>Phone</label>
<input className="form-control" onChange={(e) => setPhone} />
<button
onClick={handleNewcontact}
className="btn btn-primary mt-3 mb-4"
>
Save
</button>
</form>
</div>
);
};
export default AddUSer;
You are not passing the event to the function. You can either do
onChange={(e) => setName(e)}
onChange={(e) => setPhone(e)}
but better:
onChange={setName}
onChange={setPhone}
try this. the values are consoled when the user clicks the submit button.
const AddUSer = () => {
const [contact, setContact] = useState({id: '', userName:'', userPhone:''});
function handleNewContact(event) {
setContact({
...contact, id: Math.floor(Math.random() * 1000),
[event.target.name]: event.target.value
});
}
function handleSubmit(event) {
event.preventDefault();
console.log(contact);
}
return (
<div className="container">
<form>
<label>Name</label>
<input className="form-control" name='userName'
onChange={handleNewContact} />
<label>Phone</label>
<input className="form-control" name='userPhone'
onChange={handleNewContact} />
<button
onClick={handleSubmit}
className="btn btn-primary mt-3 mb-4"
>
Save
</button>
</form>
</div>
);
};
export default AddUSer;
I am having trouble with deleting some element from an array of React components.
I have some simple App, which has only one button "Add form", when user clicks on this button, new Form
with firstname and lastname inputes will be added. If user wants to delete this form, user can just click delete button and remove this form from an array. However, the problem is that whenever user click on delete on some form, last element becomes removed all the time. But if you look at the console, you can see that deleted form is removed from state, but in the UI last element removed.
Sample code:
import { useState } from "react";
import "./styles.css";
export default function App() {
const [forms, setForms] = useState([]);
const addNewForm = () => {
setForms([
...forms,
{
valuesOfForm: { firstname: "", lastname: "" }
}
]);
};
const handleChangeForms = (name, value, index) => {
const values = [...forms];
values[index].valuesOfForm[name] = value;
setForms([...values]);
};
const handleDeleteForms = (index) => {
const values = [...forms];
values.splice(index, 1);
setForms([...values]);
};
return (
<div className="App">
<div>
<button onClick={addNewForm}>Add new form</button>
{console.log(forms)}
{forms.map((form, index) => (
<SomeForm
value={form.valuesOfForm}
key={index}
index={index}
handleChangeForms={handleChangeForms}
handleDeleteForms={handleDeleteForms}
/>
))}
</div>
</div>
);
}
const SomeForm = (props) => {
const [value, setValue] = useState(props.value);
const onFormChange = (event) => {
props.handleChangeForms(event.target.name, event.target.value, props.index);
setValue({ ...value, [event.target.name]: event.target.value });
};
const onClick = (event) => {
event.preventDefault();
props.handleDeleteForms(props.index);
};
return (
<form onChange={onFormChange}>
<input
type="text"
name="firstname"
placeholder="first name"
onChange={onFormChange}
value={value.firstname}
/>
<input
type="text"
name="lastname"
placeholder="last name"
value={value.lastname}
/>
<button onClick={onClick}>Delete form</button>
</form>
);
};
Sandbox
Because you're using index as key. The key will help react know which one should be updated. So you need to provide a unique value for each component.
FYI: https://reactjs.org/docs/lists-and-keys.html
The quick fix for your example:
let id = 0 // Introduce id variable
export default function App() {
Increase Id each time you add new item:
const addNewForm = () => {
id++;
setForms([
...forms,
{
id,
valuesOfForm: { firstname: "", lastname: "" }
}
]);
};
Change the key to id:
<SomeForm
value={form.valuesOfForm}
key={form.id}
index={index}
Everything will work after this
The fact is I'm using an object to store all the data my form collects. In this object, I have an array, and the only solution I've found to update it is to create a function that adds every input into an array and then sets : this.setState({ 'invites': array });
But, the problem is that every change is added to the array and stored.
How can I fix this ?
<input
className="form-input"
type="email"
placeholder="nom#exemple.com"
name="invites"
onChange={e => addToArray(e, "invites")}
required
/>
function addToArray(e, name) {
emailList.push(e.target.value);
props.handleChangeArray(name, emailList);
}
handleChangeArray = (name, array) => {
this.setState({ [name]: array });
};
EDIT:
In the StackSnippet below, I have updated your example (OPs example can be found here) showing how you can get values on submit:
const { useState } = React;
const WORD_LIST = ["Foo", "Bar", "Baz", "Rock", "Paper", "Scissors", "Hello", "Goodbye"];
function InviteInput(props) {
const { value, onChange } = props;
const handleChange = e => {
onChange && onChange(e);
};
return (
<li>
<input
value={value}
onChange={handleChange}
className="form-input"
type="email"
placeholder="nom#exemple.com"
name="invites"
required
/>
</li>
);
}
function AddInviteButton(props) {
return (
<button onClick={props.onClick}>
Ajouter une autre personne // (Add another person)
</button>
);
}
function InviteForm({ onSubmit, initialInputCount }) {
const [nbInvites, setNbInvites] = useState(
[...Array(initialInputCount).keys()].map(i=>WORD_LIST[i])
);
const onAddInviteClick = () => {
//let id = nbInvites.length + 1;
setNbInvites([
...nbInvites,
//{
//id,
//***********************************************************
// THIS IS WHERE YOU SET THE DEFAULT VALUE FOR NEW INPUTS
//***********************************************************
/*value:*/ WORD_LIST[Math.floor(Math.random() * WORD_LIST.length)]
//***********************************************************
//}
]);
};
const handleChange = (event, index) => {
let newstate = [...nbInvites];
newstate[index]/*.value*/ = event.target.value;
setNbInvites(newstate);
};
const handleSubmit = event => {
onSubmit(event, nbInvites);
};
return (
<div>
{nbInvites.map((item, index) => {
return (
<InviteInput
key={index}
value={item}
onChange={e => handleChange(e, index)}
/>
);
})}
<AddInviteButton onClick={onAddInviteClick} />
<br />
<button onClick={handleSubmit}>Soumettre // Submit</button>
</div>
);
}
function App() {
const [formVals, setFormVals] = useState();
const doSubmit = (event, formValues) => {
setFormVals(formValues);
};
return (
<div className="page">
<h2 className="box-title">
Qui sont les eleves de cette classe ? // (Who are the students in this
class?)
</h2>
<p>
Vous pourrez toujours en ajouter par la suite // (You can always add
some later)
</p>
<InviteForm onSubmit={doSubmit} initialInputCount={5} />
{formVals ? <pre>{JSON.stringify(formVals, null, 2)}</pre> : ""}
</div>
);
}
ReactDOM.render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
ORIGINAL ANSWER:
You'll need to use the value prop and use event.target.value to assign the value of whatever is typed to the input.
Something like this:
function Test() {
const [inputs, setInputs] = React.useState([{
id: 1,
value: "1 initial"
}, {
id: 2,
value: "2 initial"
}]);
const handleChange = (event, index) => {
let newstate = [...inputs];
newstate[index].value = event.target.value;
setInputs(newstate);
}
const addInput = () => {
let id = inputs.length + 1;
setInputs([...inputs, {
id,
value: `${id} initial`
}])
}
return(
<div>
<button onClick={addInput}>Add Input</button>
{inputs.map((item, index) => {
return <div><input type="text" value={inputs[index].value} onChange={e=>handleChange(e,index)} /></div>
})}
</div>
);
}
ReactDOM.render(<Test />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
Instead of onChange, we can use onKeyUp to identify user typing complete event,
We can use onKeyUp event to identify user input event and debounce is to identify when user completes entering all the keywords, we need to use loadash for this functionality
It's just one line with underscore.js debounce function:
onKeyUp={e => _.debounce(addToArray(e, "invites") , 500)}
This basically says doSomething 500 milliseconds after I stop typing.
For more info: http://underscorejs.org/#debounce
Updated the above line
<input
className="form-input"
type="email"
placeholder="nom#exemple.com"
name="invites"
onKeyUp={e => _.debounce(addToArray(e, "invites") , 500)}
required
/>
function addToArray(e, name) {
emailList.push(e.target.value);
props.handleChangeArray(name, emailList);
}
handleChangeArray = (name, array) => {
this.setState({ [name]: array });
};
Source - Run javascript function when user finishes typing instead of on key up?