I have a page that passes a client item to a component, this component then passes the client item to its child component. This child component edits the client item. How can I make the child’s edits go directly to the parent item? Currently, after the edits in NewContactModal.jsx, the parent component is not affected and shows the data it had previously pulled.
Here is my code:
// Sale_resume.jsx
const { sale, selectedItems, setTotals, setCustomer } = useContext(SaleContext)
<ContactInfoModal
client={sale.customer}
show={showContactInfoModal}
handleClose={handleCloseContactInfoModal}
/>
// ContactInfoModal.jsx
const ContactInfoModal = ({ client, show, handleClose, refreshContactList }) => {
// ...
<p className='m-0 fw-bold'>Nome</p>
<p>{client.short_name}</p>
<p className='m-0 fw-bold'>CPF/CNPJ</p>
<p>{client.federal_tax_id}</p>
<NewContactModal
contact={client}
show={updateContactModalShow}
handleClose={handleCloseUpdateContactModal}
/>
// ...
}
// NewContactModal.jsx
const NewContactModal = ({ show, handleClose, contact, getContacts }) => {
const handleSubmit = async () => {
// ...
let response = {}
if (contact) {
response = await gestupApi.putContact(contact.id, { name, federalTaxId, address, neighborhood, number, zip, complement, selectedState, selectedCity, phoneNumber, email, suframa, stateTax, cityTax, contributorType, channel, birthDate })
} else {
response = await gestupApi.postContact({ name, federalTaxId, address, neighborhood, number, zip, complement, selectedState, selectedCity, phoneNumber, email, suframa, stateTax, cityTax, contributorType, channel, birthDate })
}
if (response.code == 200) {
resetStates()
getContacts ? getContacts() : ""
contact ? toast.success("Contato atualizado com sucesso") : toast.success("Contato criado com sucesso")
} else {
contact ? toast.error("Falha ao atualizar o contato") : toast.error("Falha ao criar o contato")
}
handleClose()
}
// ...
<div className="form-group">
<label className="control-label" id="full_name_label">{contributorType == "COMPANY" ? "Razão Social*" : "Nome*"}</label>
<input type="text" className='form-control' maxLength={60} onChange={(e) => setName(e.target.value)} value={name} />
</div>
<button className='btn btn-gestup' disabled={isDisabled} onClick={() => { handleSubmit() }}>Confirmar</button>
// ...
}
2
Answers
You are getting the original
sale.customer
/client
/contact
value from the Context API. That Context API seems to also make available some of the set-state-functions for its data. And it is that data you are changing in the descendent component.So you could have the NewContactModal update the data on the backend, and then update the state variable in the
SaleContext
by also using the Context API inNewContactModal.jsx
.An alternative would be to pass down a function from the parent that the child can call when the contact information has been modified, enabling the parent to do some action (such as re-fetching the data….but the NewContactModal already has the updated data, right?)
Note: the fact that this data changes variable/prop names multiple times is … likely a bad practice. When it comes to coding, Consistency Is King. Name something and try to use that name consistently. Otherwise things get really confusing for yourself, for your team mates, and worst of all….for Future You ("what the heck was I doing???")
Or you could pass a callback as prop to child and have it call the callback whenever the data updates