After adding key={ contact.id} to ContactList component, contacts (name, email, and trash icon) are not visible on clicking Add button. Id (generated by uuid) is passed from ContactCard to ContactList and then to App.js. I am new to react and its concepts. There may be a tiny mistake but I am not able to figure it out.
These components are going to be checked,
App.js
function App() {
const LOCAL_STORAGE_KEY = "contacts";
const [contacts, setContacts] = useState([]);
const addContactHandler = (contact) => {
setContacts([...contacts, {id: uuid(), ...contact }]);
};
const removeContactHandler = (id) => {
const newContactList = contacts.filter((contact) => {
return contact.id !== id;
}); setContacts(newContactList);}
useEffect(() => {
const retreiveContacts = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY));
if(retreiveContacts) setContacts(retreiveContacts);
}, []);
useEffect(() => {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(contacts));
}, [contacts]);
return (
<div className="ui container">
<Header />
<AddContact addContactHandler = {addContactHandler}/>
<ContactList contacts = {contacts} getContactId = {removeContactHandler}/>
</div> );}
ContactList.js
import React from "react";
import ContactCard from "./ContactCard";
const ContactList = (props) => {
const deleteContactHandler = (id) => {
props.getContactId(id);
};
const renderContactList = props.contacts.map((contact) => {
return <ContactCard
contact = {contact}
clickHandler = {deleteContactHandler}
key={ contact.id}/>
});
return (
<div className="ui celled list"> {renderContactList} </div>
);};
ContactCard.js
const ContactCard = (props) => {
const {id, name, email} = props.contact;
return (
<div className="item ">
<img className="ui avatar image" src={user} alt="user" />
<div className="content">
<div className="header">{name}</div>
<div>{email}</div>
</div>
<i className="trash alternate outline icon"
style={{color: "red", marginTop: "10px "}}
onClick={() => props.clickHandler(id)}></i>
</div>
);};
(Updated)
The problem was the import {uuid} from 'uuidv4';. The right way to import this is doing:
import React, {useState, useEffect} from 'react';
import './App.css';
import Header from './Header';
import AddContact from './AddContact';
import ContactList from './ContactList';
import { v4 as uuidv4 } from 'uuid';
And the setContacts in App.js needs to be like this:
setContacts([...contacts, {id: uuidv4(), ...contact }]);
I tried here and it works!
Extra tip:
I noticed that you AddContact component could be changed to be a better class component. See some changes that you could do:
constructor(props) {
super(props);
this.state = {
name: "",
email: ""
};
this.add = this.add.bind(this);
}
add = (e) => {
e.preventDefault();
if(this.state.name === "" || this.state.email === ""){
alert("All fields are mandatory");
return;
}
this.props.addContactHandler(this.state);
//clearing name and email
this.setState({name: "", email: ""});
};
Using constructor is a better way to use props in your class component, and bind your functions to use "this.add" for example.