I have a "TableConsolidado" component in which I have a button called "Test" that when clicked calls the "copiarDatos" function, in this function I do a "setDatosPorCopiar" to update the "DatosPorCopiar" state, in turn I handle a useEffect that when the state of this "DatosPorCopiar" changes, it will perform an action that is "mapDatosPorCopiar" in which I save data in firestore, the problem is that when I click on the "Test" button the component does not update
const TableConsolidado = ({ confirmDelete, data, names, anio, mes }) => {
const [datosPorCopiar, setDatosPorCopiar] = useState([]);
const [helper, setHelper] = useState(false);
const copiarDatos = () => {
const meses = [
"diciembre",
"enero",
"febrero",
];
let mesAnterior;
let anioNuevo = anio;
if (mes === "diciembre") {
// si el caso es diciembre, entonces el anterior es noviembre.
mesAnterior = "noviembre";
} else {
// en cualquier otro caso, el mes anterior es el que se encuentra una posición antes en el arreglo de meses.
const indiceMesActual = meses.indexOf(mes);
mesAnterior = meses[indiceMesActual - 1];
}
if (mesAnterior === "diciembre") {
anioNuevo = anio - 1;
}
data
.filter((dat) => dat.mes === mesAnterior && dat.anio === anioNuevo)
.map((da) =>
setDatosPorCopiar((prevState) => [
...prevState,
{
anio: da.anio,
dni: da.dni,
id: da.id,
lastName: da.lastName,
mes: da.mes,
montoPagado: da.montoPagado,
name: da.name,
notas: da.notas,
phone: da.phone,
price: da.price,
roomName: da.roomName,
},
])
);
console.log("se ejecuto copiar datos (pasar datos al state)");
};
const mapDatosPorCopiar = async () => {
datosPorCopiar.map(async (datos) => {
await addDoc(consolidadosCollection, {
dni: datos.dni,
anio: datos.anio,
mes: mes,
lastName: datos.lastName,
name: datos.name,
phone: datos.phone,
price: datos.price,
roomName: datos.roomName,
});
console.log("se guardaron los datos en la bd");
});
};
useEffect(() => {
if (datosPorCopiar.length > 0) {
console.log("ingreso al use effect y ejecuto");
mapDatosPorCopiar();
} else {
console.log("ingreso pero no ejecuto");
}
}, [datosPorCopiar]);
return (
<>
<hr />
<div className="container">
<div className="row">
<div className="col">
<div className="d-grid gap-2">
<Link
to="/createconsolidado"
state={{ names: names, anio: anio, mes: mes }}
className="btn btn-secondary mt-2 mb-2"
>
CREATE
</Link>
</div>
<table className="table table-dark table-hover">
<thead>
<tr>
<th>CUARTO</th>
<th>DNI</th>
<th>NOMBRES</th>
<th>APELLIDOS</th>
<th>TELEFONO</th>
<th>PRECIO</th>
<th>MONTO PAGADO</th>
<th>NOTAS</th>
<th>ACCION</th>
</tr>
</thead>
<tbody>
{data
.filter((dat) => dat.mes === mes && dat.anio === anio)
.map((dat) => (
<tr key={dat.id}>
<td>{dat.roomName}</td>
<td>{dat.dni}</td>
<td>{dat.name}</td>
<td>{dat.lastName}</td>
<td>{dat.phone}</td>
<td>{dat.price}</td>
<td>{dat.montoPagado}</td>
<td>{dat.notas}</td>
<td>
<Link
to={`/edit/${dat.id}`}
state={{ names: names }}
className="btn btn-light"
>
<i className="fa-solid fa-pencil"></i>
</Link>
<button
onClick={() => {
confirmDelete(dat.id);
}}
className="btn btn-danger"
>
<i className="fa-solid fa-trash"></i>
</button>
</td>
</tr>
))}
</tbody>
</table>
<button onClick={copiarDatos} value={mes}>
Test
</button>
</div>
</div>
</div>
</>
);
};
export default TableConsolidado;
If more information is needed, please leave me a comment so I can update the post
I want the component to be updated when I click on the "test" button
I would say that the problem is that you are rending the data from the prop data. And if the data prop doesn't update there will be no changes in the dom to update.
So my guess is that the parent (or where the data comes from needs to be updated up there somewhere).
You can test this by changing data for datosPorCopiar and you will see changes. But I guess this is not what you want in the end.
// This is the data I'm talking about.
{data
.filter((dat) => dat.mes === mes && dat.anio === anio)
.map((dat) => (
<tr key={dat.id}>
<td>{dat.roomName}</td>
<td>{dat.dni}</td>
<td>{dat.name}</td>
<td>{dat.lastName}</td>
<td>{dat.phone}</td>
<td>{dat.price}</td>
<td>{dat.montoPagado}</td>
<td>{dat.notas}</td>
<td>
<Link
to={`/edit/${dat.id}`}
state={{ names: names }}
className="btn btn-light"
>
<i className="fa-solid fa-pencil"></i>
</Link>
<button
onClick={() => {
confirmDelete(dat.id);
}}
className="btn btn-danger"
>
<i className="fa-solid fa-trash"></i>
</button>
</td>
</tr>
))}
Related
I have a problem in React. The problem in question is about the use of the memo, basically, I have a list generator application, and I use the memo in the list item(child) component, so far so good, working.
The problem is that when I export functions through props, that is, functions from the parent component to the child component, the memo doesn't work.
The goal is for the memo, to do its default purpose with the list items, and not render everything in the virtual dom.
import React from 'react'
import {memo} from 'react'
import "./Task.css"
import junk from "../../img/junk.png"
import star from "../../img/star.png"
import starFull from "../../img/star-full.png"
import verifyFull from "../../img/verify-full.png"
import verify from "../../img/verify.png"
const Task = (props) => {
return (
<div className='task'>
<div className='task_title'>
<h2>{props.title}</h2>
<div className='task_settings' >
<button onClick={props.handleFavorite}><img src= {props.favorite?starFull:star} alt="" /></button>
<button onClick={props.handleComplete}><img src= {props.complete?verifyFull:verify} alt="" /></button>
<button onClick={props.handleDelete} ><img src={junk} alt="" /></button>
</div>
</div>
<div className='task_description'>
{props.description}
</div>
<div>
{props.date}
</div>
</div>
)
/------------------------------------------
import './TaskManeger.css'
import {Task} from "../../components";
import React, {useState,useEffect,memo} from 'react'
const TaskManeger = () => {
const [formValues,setValues] = useState({
title:"",
description:"",
date:""}
)
const [list,setList] = useState([]
)
function maskDate(value) {
return value
.replace(/\D/g, "")
.replace(/(\d{2})(\d)/, "$1/$2")
.replace(/(\d{2})(\d)/, "$1/$2")
.replace(/(\d{4})(\d)/, "$1");
};
function handleInput(e) {
const {name,value} = e.target
setValues(name==="date"?{...formValues,[name]:maskDate(value)}:{...formValues,[name]:value})
}//set values in input
function handleSubmit(e) {
e.preventDefault()
const formData = new FormData(e.target)
const data = Object.fromEntries(formData)
addTask(data)
}//creat object with values for input
function handleAddFavorite(id) {
setList(list.map( itemList => {return itemList.id === id ? { ...itemList, favorite: !itemList.favorite } : itemList}))
}
function handleAddComplete(id) {
setList(list.map( itemList => {return itemList.id === id ? { ...itemList, complete: !itemList.complete } : itemList}))
}
function deleteTask(item) {
setList(list.filter(i=> i.id !== item.id))
}
function addTask(e) {
setList([...list,{title:e.title, description:e.description, date:e.date, id:list.length,favorite:false,complete:false}])
}//creat object in list
useEffect(() => {
setList([...list,
{title:"Siga As Instrtuções ", description:"Abaixo nos temos varias tarefas, e nos iremos passar por um tutorial em cada uma delas, siga e conforme for completando-as, conclua no icone de visto a acima.", date:"", id:0,favorite:false},
{title:"Crie Suas Tarefas", description:"Ao lado, podemos ver um formulario, onde você pode preencher as informações para você mesmo criar suas tarefas.", date:"", id:1,favorite:false},
{title:"Favorite Suas Tarefas", description:"Você pode favoritar as tarefas atravez da estrela que esta acima, a direita do seu titulo.", date:"", id:2,favorite:false},
{title:"Apague Suas Tarefas", description:"Você pode apagar as tarefas atravez da lixeira que esta acima, a direita do seu titulo.", date:"", id:3,favorite:false},
{title:"Filtre", description:"Alem disso tudo que ja falamos nas tarefas anteriores, você pode filtrar suas tarefas, caso queira ver apenas as completadas, ou as que ainda faltam ser completadas, as favoritas, ou todas.", date:"", id:4,favorite:false}])
}, [])
return (
<div className="tasks">
<div className="tasks_container">
<div className="task_generator">
<form onSubmit={handleSubmit}>
<input placeholder='Titulo' name='title' type="text" onChange={handleInput} value={formValues.title}/>
<input placeholder='Descrição' name='description' type="text" onChange={handleInput} value={formValues.description} />
<input placeholder='Data' name='date' onChange={handleInput} value={formValues.date} />
<button type="submit">Criar</button>
</form>
</div>
<div className="task_list">
<div className='task_filter'>
<div>Filtrar ▼</div>
<p>Todos</p>
<p>Completados</p>
<p>Favoritos</p>
</div>
{list.map( itemList =>(
<Task
key={itemList.id}
title={itemList.title}
description={itemList.description}
date={itemList.date}
handleDelete={()=>deleteTask(itemList)}
handleFavorite={()=>handleAddFavorite(itemList.id)}
handleComplete={()=>handleAddComplete(itemList.id)}
id={itemList.id}
favorite={itemList.favorite}
complete={itemList.complete}
/>
))}
</div>
</div>
</div>
)
}
export default TaskManeger
The memo is not working because the functions you are passing in are not referentially stable
handleDelete={()=>deleteTask(itemList)}
handleFavorite={()=>handleAddFavorite(itemList.id)}
handleComplete={()=>handleAddComplete(itemList.id)}
You create three new functions on every render and pass them as prop. memo tests for referential equality (===) of each prop, but (() => x) !== (() => x).
You could pass in the functions like so:
handleDelete={deleteTask}
handleFavorite={handleAddFavorite}
handleComplete={handleAddComplete}
and make the child component pass the argument instead.
You would also need to use useCallback for those functions to get stability.
const deleteTask = useCallback((item) => {
setList(list => list.filter(i => i.id !== item.id))
}, [setList])
// repeat pattern for all three functions
I am creating a data table, fetching data from Redux store, and setting up this Redux's raw data into a useState hook named rowsData, setRowsData for data table rows,
The data from redux is array of objects.
I then set the rowsData into a new [data, setData] useState because of some additional data, like meta information for pagination.
useEffect(() => {
const rawRows =
users.allUsers &&
users.allUsers.data.map((user) => {
return {
name: (
<Link
to={`/users/profile/view/${user.secondaryId}`}
className="d-flex justify-content-start align-items-center"
>
<div className="me-3">
<AvatarWord initial={user.name[0]} />
</div>
<h5 className="text-primary mt-2"> {user.name}</h5>
</Link>
),
primaryRole: primaryRoleBackground(
user.primary_role
? user.primary_role.name[0].toUpperCase() +
user.primary_role.name.slice(1)
: ""
),
// primary_role: primaryRoleBackground(user.primary_role),
id: user.id,
email: user.email,
status: <div>{userStatus(user.status, user.id)}</div>,
Here I am adjusting it according to data table. The last line ````Status: ``` has a function to discriminate the active and inactive users with a button to activate or deactivate them.
const userStatus = (status, id) => {
switch (status) {
case "0":
return (
<>
<span className="legend-indicator bg-danger text-dark"></span>
Inactive
<Link
to="#!"
type="button"
className="btn badge bg-success ms-2"
onClick={() => userActivator(id)}
>
Activate
</Link>
</>
);
case "1":
return (
<>
<span className="legend-indicator bg-success text-dark"></span>
Active
<Link
to="#!"
type="button"
className="btn badge bg-danger ms-2"
onClick={() => userDeactivator(id)}
>
Deactivate
</Link>
</>
);
default:
return;
}
};
Here is the output of the codes above.
now when I click on deactivate I use the following code to update the data.
const userDeactivator = (id) => {
// deactivateUser(id);
console.log(rowsData.length);
for (let i = 0; i === dataLength; i++) {
const res = rowsData[i].id === id;
setRowsData([
...rowsData,
{
...res,
status: (
<div>
<>
<span className="legend-indicator bg-danger text-dark"></span>
Inactive
<Link
to="#!"
type="button"
className="btn badge bg-success ms-2"
onClick={() => userActivator(res.id)}
>
Activate
</Link>
</>
</div>
),
},
]);
}
};
I sure sends the API call to deactivate the user, but I have to update the data status in runtime. What I am missing I cannot figure out.
In useEffect hook you have to pass the argument of status like this:
useEffect(() => {
return () => {
// Your Code
}
}, [status])
This would tell the useEffect that whenever the status changes you have to re-render the state for it.
I'm having some issues with the useState hook and i can't understand why this doesn't work.
I'm building a simple ticket system, and whenever a user clicks on a button it opens a modal and the user can write things about their issue.
I'm having problems getting this modal data to display on another page, where the user can see all the tickets, like a list.
If i do a console.log i can see the user input, but if a try to print this into the page itself it doesn't work.
Throws an error saying TypeError: addTicket is not a function
And lastly i'd like to show the modal info in a format(ID - Title - Status), how can i proceed about the id part, for it to iterate itself every submit event?
Many thanks!
Code on the list page
const Home = () => {
const [showModal, setShowModal] = useState(false);
const openModal = () => {
setShowModal(prev => !prev)
}
const[tickets, setTickets] = useState([]);
const addTicket = ( title ) =>{
setTickets([...tickets, { title }])
}
return(
<>
<PageContainer>
<HeaderContainer>
<img src={ gugale } alt="logo-left"/>
<img src={ logo } alt="logo-right"/>
</HeaderContainer>
<TicketsContainer>
<CreateTicketModal showModal={ showModal } setShowModal= { setShowModal }/>
<TicketsTop>
<p>Seus tickets</p>
<button onClick={openModal}>Novo ticket</button>
</TicketsTop>
<TicketTitles>
<p>ID</p>
<p>Título</p>
<p>Status</p>
</TicketTitles>
<TicketsInfo>
{ tickets.map(ticket => {
<p> {ticket.name} </p>
})}
</TicketsInfo>
</TicketsContainer>
</PageContainer>
<GlobalStyle/>
</>
)
}
Code on the modal page
const CreateTicketModal = ({showModal, setShowModal, addTicket}) => {
const [ title, setTitle] = useState("");
const handleName = (e) => {
setTitle(e.target.value);
}
const handleSubmit = (e) => {
e.preventDefault();
addTicket(title);
}
return (
<>
{showModal ? (
<Background showModal={showModal}>
<ModalWrapper>
<ModalHeader>
<p className="createNew" >Criar Novo Ticket</p>
<button className="closebtn" onClick={() => setShowModal(prev => !prev)}><FiX className="icon"></FiX></button>
</ModalHeader>
<form onSubmit={ handleSubmit } >
<p className="ticketTitle">Título</p>
<input type="text" name="ticketInput" placeholder="Escreva uma breve descrição sobre o problema" required onChange={ handleName } className="titleInput"/>
<p className="dscptTitle">Descrição</p>
<textarea type="text" name="dscpInput" placeholder="Escreva detalhadamente a sua solicitação..." className="dscpInput"/>
<p className="anex">Anexos</p>
<p className="anexDscp">Envie-nos arquivos, imagens ou textos que possam contribuir para a verificação da solicitação</p>
<Anex>
<FiUploadCloud className="anexCloud"></FiUploadCloud>
<p>Arraste e solte arquivos aqui ou</p>
<button>Selecione aqui</button>
</Anex>
<button addTicket={ addTicket }className="addTkt">Adicionar ticket</button>
</form>
</ModalWrapper>
<GlobalStyle/>
</Background>
): null}
</>
)
}
I believe that you are missing to pass addTicket function as prop to the CreateTicketModal
component
<CreateTicketModal showModal={showModal} setShowModal= {setShowModal} addTicket={addTicket} />
You need to pass addTicket to the Modal component as props as <CreateTicketModal addTicket={addTicket} ... /> to access it in the child component.
Using React.Js, I created a delete function to delete an item from a table. the delete is working fine but what I want to do is that after deleting I want the tables to be dynamically updated to show only the items left. Now after the delete I have to refresh manually the page or go to another page and comeback to see the items left after the delete
This is the code built so far :
import React, { Component } from "react";
import { Card, Button, Select,/* message, */ Form, Tooltip } from "antd";
import extraitMP3 from "./data";
import { arrayMove, SortableHandle } from "react-sortable-hoc";
import ContainerHeader from "components/ContainerHeader/index";
import { getExtraitMp3, hideMessageUpdate, showUpdateLoader, updateMp3Visibilite } from "appRedux/actions/Comedien";
import { deleteMp3Request } from "../../../appRedux/services/extraitMp3Service"
import { connect } from "react-redux";
import { NotificationContainer, NotificationManager } from "react-notifications";
import { userSignOut } from "appRedux/actions/Auth";
import { displayIcon } from '../../../util/Icon.js';
import CircularProgress from "components/CircularProgress";
import { Modal } from "antd";
const extraitMP32 = [extraitMP3];
const confirm = Modal.confirm;
const Option = Select.Option;
const DragHandle = SortableHandle(() =>
<span className="gx-draggable-icon gx-pt-2">
<i className="icon icon-menu" style={{ fontSize: 25 }} />
</span>);
class ListExtrait extends Component {
onSortEnd = ({ oldIndex, newIndex }) => {
this.setState({
extraitMP3: arrayMove(this.state.extraitMP3, oldIndex, newIndex),
});
};
constructor() {
super();
this.state = {
extraitMP3: extraitMP32[0],
nombreMP3: {
rechercheExtraits: 0,
recherchePossible: 0,
extraitFiche: 0,
extraitFichePossible: '',
extraitArchives: 0,
extraitArchivesPossible: '',
},
loader: false,
}
}
componentDidMount() {
this.props.getExtraitMp3();
}
componentDidUpdate() {
}
static getDerivedStateFromProps(nextProps, prevState,/* nextProps2,prevState2 */) {
if (nextProps.extraitMP3 !== prevState.extraitMP3 && nextProps.extraitMP3) {
return { extraitMP3: nextProps.extraitMP3 };
}
else return null;
}
showDeleteConfirmation(value, id, index, thisHandler) {
confirm({
title: 'Voulez vous supprimer cette audio ?',
content: '',
okText: 'Oui, je confirme',
okType: 'danger',
cancelText: 'Non',
onOk() {
deleteMp3Request(id);
const { extraitMP3 } = thisHandler.state;
Object.keys(extraitMP3).splice(index, 1);
NotificationManager.success("le fichier audio est supprimé avec succès !", "");
},
onCancel() {
},
});
}
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
this.props.showUpdateLoader();
this.props.updateMp3Visibilite(values);
}
});
};
render() {
const { loader, extraitMP3 } = this.state;
const selectOptions = new Map([
[1, "Visible dans la recherche et sur ma fiche"],
[2, "Visible sur ma fiche uniquement"],
[3, "Masqué"],
]);
console.log('extraitMP3', extraitMP3)
function handleChangeSelect(value) {
console.log(`selected ${value}`);
}
return (
<div>
{loader ? <CircularProgress className="gx-loader-400" /> : Object.keys(extraitMP3).map((ids, index) => {
return (
<Card>
<li key={ids}>
<Card styleName="gx-card-list icon icon-data-display gx-mr-2 gx-text-blue gx-fs-xl">
<div className="gx-media-body">
{extraitMP3[ids].Typenom}
{extraitMP3[ids].TypeIcon != null &&
displayIcon(extraitMP3[ids].TypeIcon)
}
</div>
{Object.keys(extraitMP3[ids].TypeMp3List).map(idJson => {
return (
<div className="gx-main-content gx-mb-4">
<ContainerHeader match={this.props.match} />
<div className="gx-contact-item gx-dragndrop-item">
<DragHandle />
<div className="gx-col gx-job-title ">
{extraitMP3[ids].TypeMp3List[idJson].intitule}
</div>
{extraitMP3[ids].TypeMp3List[idJson].interpretation1Icon !== '' &&
<Tooltip title={extraitMP3[ids].TypeMp3List[idJson].interpretation1Nom}>
{displayIcon(extraitMP3[ids].TypeMp3List[idJson].interpretation1Icon)}
</Tooltip>
}
{extraitMP3[ids].TypeMp3List[idJson].interpretation2Icon !== '' &&
<Tooltip title={extraitMP3[ids].TypeMp3List[idJson].interpretation2Nom}>
{displayIcon(extraitMP3[ids].TypeMp3List[idJson].interpretation2Icon)}
</Tooltip>
}
{extraitMP3[ids].TypeMp3List[idJson].interpretation3Icon !== '' &&
<Tooltip title={extraitMP3[ids].TypeMp3List[idJson].interpretation3Nom}>
{displayIcon(extraitMP3[ids].TypeMp3List[idJson].interpretation3Icon)}
</Tooltip>
}
{extraitMP3[ids].TypeMp3List[idJson].langueIcon !== '' &&
<div className="gx-col gx-job-title gx-d-sm-flex gx-text-truncate gx-px-8">
<Tooltip title={extraitMP3[ids].TypeMp3List[idJson].langueNom}>
<i className={`flag flag-24 gx-mr-2 ${extraitMP3[ids].TypeMp3List[idJson].langueIcon}`} />
</Tooltip>
</div>
}
<div className="gx-col gx-job-title gx-d-sm-flex gx-text-truncate gx-px-8">
<Select
showSearch
style={{ width: '100%' }}
placeholder="Selection la choix de votre numéro de téléphone "
optionFilterProp="children"
onChange={handleChangeSelect}
defaultValue={selectOptions.get(extraitMP3[ids].TypeMp3List[idJson].visibilite)}
filterOption={(input, Option) => Option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
>
{[...selectOptions].map(([value, label]) => <Option value={value}> {label} </Option>)}
</Select>
</div>
<div className="gx-col gx-job-title gx-d-sm-flex gx-text-truncate gx-px-8">
<i className="icon icon-edit gx-fs-xl gx-text-gris" />
</div>
<div className="gx-col gx-job-title gx-d-sm-flex gx-text-truncate gx-px-8">
<span className="gx-pointer">
<i className="icon icon-trash gx-pointer gx-text-danger gx-fs-xxl"
id={extraitMP3[ids].TypeMp3List[idJson].id}
onClick={e => this.showDeleteConfirmation(e.target.value, extraitMP3[ids].TypeMp3List[idJson].id, index, this)} />
</span>
</div>
</div>
</div>
)
})}
<NotificationContainer />
<Button type="primary" htmlType="submit" labelCol={{ xs: 24, sm: 5 }} wrapperCol={{ xs: 24, sm: 12 }}>
Enregistrer
</Button>
</Card>
</li>
</Card>
)
})}</div>
)
}
}
const VisibiliteFormMp3 = Form.create()(ListExtrait);
const mapStateToProps = ({ comedien }) => {
const {
extraitMP3,
alertMessageUpdate,
showMessageUpdate
} = comedien;
return {
extraitMP3,
alertMessageUpdate,
showMessageUpdate
}
};
export default connect(
mapStateToProps,
{
userSignOut,
getExtraitMp3,
hideMessageUpdate,
showUpdateLoader,
updateMp3Visibilite
})(VisibiliteFormMp3);
extraitMP3 is an object of objects that's why I used Object.keys(extraitMP3)
I didn't know how to update the state correctly.
this is the view :
You should put your data in state and then change the state. After changing the state the page automatically re-rendered and changed data of your state will be shown.
So in your delete function simply delete your chosen data and give your remaining data to your state.
Hope this helps, feel free to ask questions if I couldn't explain myself clearly.
I believe you can do this by calling something like and then just call this from within your delete
refreshMp3(){
this.setState({getExtraitMp3: !this.state.getExtraitMp3});}
One of the ideas of React is to make the functionality you ask for simple to implement and it would update automatically. I'm going to abstract a bit from your example. Think about your data in terms of what updates along with the UI. This way we can simplify your component. You have some items that you put in a table. Each item is a row and can be inside an array. We put that array in the state.
class ListExtrait extends Component {
constructor() {
super();
this.state = {
rowsForTable: [...],
somethingElse...
}
...
Then in the JSX in the render method you can render the table rows using map:
rowsForTable.map(item => <div/li/whatever>{item.name or something else}</div>
This way whenever an item is gone from rowsForTable the component will automatically update it's view and the table rows will be up to date.
You can simply call the function while clicking the delete button say deleteHandler. On that function call the api you have made to delete the item and then after successfull delete again call the api that will show the item from database after certain time interval.
Code:
import React, { Component } from 'react'
export default class show_schedule extends Component {
render() {
state={
}
show_item_after_delete=()=>{
setTimeout(()=>{
axios.get(`http://127.0.0.1:8000/account/api/show_item/`).then(res=>{
console.log('delete schedule data ',res.data)
})
},500)
}
deleteHandler=()=>{
axios.delete(`http://127.0.0.1:8000/account/api/delete_item/${id}`).then(res=>{
console.log(res.data)
})
this.show_item_after_delete()
}
return (
<div>
<button onClick={this.deleteHandler}>Delete</button>
</div>
)
}
}
I try to update data in react firebase application. Everything work fine, i can recover the right data in a modal, and modify them.
But, when I set my data to firebase (with a function "updateContent), my entire collection of item is delete because I did not specify the exact path of the selected item. So, to do that, I need to recover the ID of the selected Item in my function. My problem: I manage to retrieve all the information of my element, but not its ID. I try many thing, console.log every function with ID item, every thing it's okay except for my modal and my function "updateContent" (while the other information of my element is displayed without any problem)
Can you give me a little help ? Thank you in advance.
This is my code for each item, when function to pass the data from my Hit Component to my modal Component (modal is for modify item data):
function handleClick (hit, onEdit) {
onEdit({id: hit.objectID, marque: hit.marque, numero: hit.numero, reference: hit.reference, marquesuite: hit.marquesuite, cote: hit.cote})
}
const Hit = ({hit, onEdit}) =>
<div className="item" id={hit.objectID}>
<img src={hit.avatarURL} width={150} height={150}></img>
<h1 className="marque">{hit.marque}</h1>
<h3 className="numero">{hit.numero}</h3>
<h4 className="reference">{hit.reference}</h4>
<h4 className="marquesuite">{hit.marquesuite}</h4>
<p className="cote">{hit.cote}</p>
<button className="btn btn-warning" onClick={() => handleClick(hit, onEdit) }>Modifier</button>
<button className="btn btn-danger" onClick={() => removeToCatalogue(hit)}>Supprimer</button>
</div>
const Content = ({ onEdit, }) => {
const EnhancedHit = props =>
<Hit onEdit={ onEdit } { ...props } />
return (
<div className="text-center">
<Hits hitComponent={ EnhancedHit } />
</div>
)
}
And now, this is my modal component:
updateContent = (e) => {
e.preventDefault();
const catalogue = {
marque: this.state.marque,
marquesuite: this.state.marquesuite,
numero: this.state.numero,
reference: this.state.reference,
cote: this.state.cote,
id: this.state.key,
}
console.log(catalogue)
//firebase.database().ref(`catalogue`/).set(catalogue);
};
onOpenModal = (hit) => {
this.setState({ open: true, id: hit.objectID, marque: hit.marque, numero: hit.numero, reference: hit.reference, marquesuite: hit.marquesuite, cote: hit.cote });
console.log(hit.marque, hit.id)
};
onCloseModal = () => {
this.setState({ open: false });
};
onInputChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
render (){
const { open } = this.state;
<h1 className="text-center">Catalogue de capsule</h1>
<InstantSearch
apiKey="xxx"
appId="xxx"
indexName="xxx>
<SearchBox translations={{placeholder:'Rechercher une capsule'}} width="500 px"/>
<Content onEdit={this.onOpenModal}/>
<Modal open={open} onClose={this.onCloseModal} center>
<form onSubmit={this.updateContent} key={this.state.objectID}>
<h2>Modification de la capsule :</h2>
<p>Marque de la capsule:<input type="text" class="form-control" name="marque" value={this.state.marque} onChange={this.handleChange}></input></p>
<p>Numéro de la capsule:<input type="text" class="form-control" name="numero" value={this.state.numero} onChange={this.handleChange}></input></p>
<p>Référence de la capsule:<input type="text" class="form-control" name="marquesuite" value={this.state.marquesuite} onChange={this.handleChange}></input></p>
<p>Référence de la capsule (suite):<input type="text" class="form-control" name="reference" value={this.state.reference}onChange={this.handleChange}></input></p>
<p>Cote de la capsule:<input type="text" class="form-control" name="cote" value={this.state.cote}onChange={this.handleChange}></input></p>
<button className="btn btn-success">Mettre à jour</button>
</form>
</Modal>
</InstantSearch>
I find the solution. It was just given the same name in id props like this:
onEdit({objectID: hit.objectID ...})
onOpenModal = (hit) => {
this.setState({ open: true, objectID: hit.objectID, ... });
};