I'm working on react-phonebook app. I'm unable to understand the correct logic to edit the contact details.
On clicking the edit button, I need to show the form and put name and number of that particular contact in the input fields and then take user input as the edited contact and display it in the list.
I'm facing the following issues:
If showForm is false, it gives the error
Cannot set properties of null (setting 'value')
although I've added setShowForm(true) in handleEdit function but it still shows error but works when the form is already showing.
Here is the code:
import React, { useState } from "react";
const App = () => {
let phoneBookData = [{ name: "John Doe", number: 12345678 }];
const [contacts, setContacts] = useState(phoneBookData);
const [showForm, setShowForm] = useState(false);
const [userName, setUserName] = useState("");
const [number, setNumber] = useState("");
const handleDelete = (index) => {
console.log("index:", index);
let selectedIndex = index;
let newContacts = contacts.filter(
(_contact, index) => index !== selectedIndex
);
setContacts(newContacts);
};
const handleAddContact = () => {
if (userName.length === 0) {
alert("Please enter a valid name.");
return;
} else if (userName.includes("1")) {
alert("Name cannot contain any number or special character.");
return;
} else if (number.length === 0) {
alert("Please enter a valid number.");
return;
}
let newContact = { name: userName, number: number };
setContacts([...contacts, newContact]);
setUserName("");
setNumber("");
};
const handleEdit = (index) => {
setShowForm(true);
document.getElementById("number").value = number;
document.getElementById("name").focus();
document.getElementById("name").value = userName;
};
return (
<div id="main">
<div className="container-fluid">
<div className="row">
<div className="col-md-4"></div>
<div className="col-md-4">
<div className="App">
<h2 className="header">PhoneBook App</h2>
<span
style={{
cursor: "pointer",
color: "blue",
textDecoration: "underline",
}}
onClick={() => setShowForm(!showForm)}
>
{showForm ? "Hide Contact Form" : "Create New Contact"}
</span>
{showForm && (
<div className="container">
<form className="form">
<div className="form-group">
<input
type="text"
className="form-control"
placeholder="Name"
value={userName}
onChange={(e) => setUserName(e.target.value)}
id="name"
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control"
placeholder="Number"
value={number}
onChange={(e) => setNumber(e.target.value)}
id="number"
/>
</div>
<button
type="button"
className="btn btn-primary icon-holder"
onClick={handleAddContact}
>
Add
</button>
</form>
</div>
)}
<p>There are {contacts.length} contacts saved in this book.</p>
{contacts.map((contact, index) => (
<div key={index} className="contacts">
<div className="contact-details">
<h5>
{index + 1}) {contact.name}
</h5>
<p>{contact.number}</p>
</div>
<button
className="icon-holder"
onClick={() => handleEdit(index)}
>
Edit
</button>
<button
className="icon-holder"
onClick={() => {
handleDelete(index);
}}
>
Delete
</button>
<hr />
</div>
))}
</div>
</div>
<div className="col-md-4"></div>
</div>
</div>
</div>
);
};
export default App;
Here is the link to codesandbox: https://codesandbox.io/p/sandbox/todos-app-listed-rxsd3p?file=%2Fsrc%2FApp.js%3A6%2C51
Don't use DOM selectors like
document.getElementById.In your case, the selectors return
nullbecause the corresponding elements are not yet on the page when you try to select them.Solution: get rid of the three
document.getElementByIdcalls, and add theautoFocusprop to the field you want to focus.If you need a reference to an actual DOM element, read into
useRef.