Reputation: 89
Trying to implement a function that adds a new value to my ReactJS table.
When i click the button "cadastrar" in the Formulario component it should send a new object to the parent's component and re-render the table rows.
I'm trying really hard to make this application work, don't see why its not working propperly.
my objective with that is that the table is supposed to keep it's old values adding a new row with the new values from the forms.
Exact error when i click the button: https://i.sstatic.net/vpT2u.jpg
Parent's component:
import './App.css';
import React, {useState} from 'react';
import {Table, Jumbotron, Button} from 'react-bootstrap'
import Formulario from './Formulario'
import renderCadastros from './renderCadastros'
function App() {
const [Cadastros, setCadastros] = useState([{
"id": 1,
"nome": "Francisca Julia da Costa",
"cpf": "457.696.936-65",
"rg": "47.360.897-2",
"data_nasc": "23/03/1944",
"sexo": "Feminino"
},
{
"id": 2,
"nome": "Noah Felipe Silva",
"cpf": "956.531.431-70",
"rg": "40.974.782-8",
"data_nasc": "11/07/1964",
"sexo": "Masculino"
},
{
"id": 3,
"nome": "Alícia Rosângela Melo",
"cpf": "066.291.353-18",
"rg": "36.214.141-1",
"data_nasc": "18/02/1978",
"sexo": "Feminino"
}])
function atualizarCadastros(novoCadastro){
setCadastros(cadastrosAtuais => {
return [cadastrosAtuais, novoCadastro]
})
}
return (
<Jumbotron style={{background: 'transparent'}}>
<Formulario atualizarCadastros={atualizarCadastros} />
<Table striped bordered hover size='sm'>
<thead>
<tr>
<th>id</th>
<th>Nome</th>
<th>CPF</th>
<th>RG</th>
<th>Nascimento</th>
<th>Sexo</th>
<th></th>
</tr>
</thead>
<tbody>
{Cadastros.map(renderCadastros)}
</tbody>
</Table>
</Jumbotron>
);
}
export default App;
Component that creates the table rows based on it's parent state:
import './App.css';
import React from 'react';
import {Button} from 'react-bootstrap'
function renderCadastros(cadastro, index){
return(
<tr id={cadastro.id} key={index}>
<td>{cadastro.id}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.nome}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.cpf}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.rg}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.data_nasc}</td>
<td contentEditable="true" suppressContentEditableWarning={true}>{cadastro.sexo}</td>
<td align="center"><Button variant="danger">Excluir</Button></td>
</tr>)
}
export default renderCadastros
Component that creates the form and has the function to add a new value to its parent state:
import './App.css';
import React, {useState, useRef} from 'react';
import {Button, Form, Col} from 'react-bootstrap'
function Formulario ({atualizarCadastros}){
const [novoCadastro, setCadastros] = useState()
const refId = useRef()
const refNome = useRef()
const refCpf = useRef()
const refRg = useRef()
const refNascimento = useRef()
const refSexo = useRef()
function registrarCadastros(){
const id = refId.current.value
const nome = refNome.current.value
const cpf = refCpf.current.value
const rg = refRg.current.value
const nascimento = refNascimento.current.value
const sexo = refSexo.current.value
setCadastros({'id': id, 'nome': nome, 'cpf': cpf, 'rg': rg, 'data_nasc': nascimento, 'sexo': sexo})
atualizarCadastros(novoCadastro)
}
return(
<div>
<Form>
<Form.Row>
<Col>
<Form.Label>Identificação</Form.Label>
<Form.Control ref={refId} placeholder="Id" />
</Col>
<Col>
<Form.Label>Nome Completo</Form.Label>
<Form.Control ref={refNome} placeholder="João Silva" />
</Col>
<Col>
<Form.Label>CPF</Form.Label>
<Form.Control ref={refCpf} placeholder="000.000.000-00" />
</Col>
<Col>
<Form.Label>RG</Form.Label>
<Form.Control ref={refRg} placeholder="0.000.000" />
</Col>
<Col>
<Form.Label>Data de Nascimento</Form.Label>
<Form.Control ref={refNascimento} placeholder="DD/MM/AAAA" />
</Col>
<Col>
<Form.Label>Sexo</Form.Label>
<Form.Control ref={refSexo} placeholder="Masculino/Feminino" />
</Col>
</Form.Row>
</Form>
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
<Button onClick={registrarCadastros} style={{margin: '10px'}} variant="primary">Cadastrar</Button>
</div>
</div>
)
}
export default Formulario
Upvotes: 0
Views: 49
Reputation: 3496
I think this function should little fix.
the function right now:
function atualizarCadastros(novoCadastro){
setCadastros(cadastrosAtuais => {
return [cadastrosAtuais, novoCadastro]
})
}
when we call atualizarCadastros({ c: 3 }), and we have cadastrosAtuais = [{ a: 1 }]
we get new Cadastros as [[{ a: 1 }], { c: 3 }]
.
but we want to get [{ a: 1 }, { c: 3 }]
so we can use spread syntax:
function atualizarCadastros(novoCadastro) {
setCadastros(cadastrosAtuais => {
return [...cadastrosAtuais, novoCadastro];
})
}
or better use concat:
function atualizarCadastros(novoCadastro) {
setCadastros(cadastrosAtuais => {
return cadastrosAtuais.concat(novoCadastro);
})
}
Upvotes: 1
Reputation: 3032
when you write like this
setCadastros({'id': id, 'nome': nome, 'cpf': cpf, 'rg': rg, 'data_nasc': nascimento, 'sexo': sexo})
atualizarCadastros(novoCadastro)
novoCadastro contains an old one as its value was read before setCadastros was called, so you can create an object and pass it to both: local state handler and to parent component function
const superNovoCadastro = {'id': id, 'nome': nome, 'cpf': cpf, 'rg': rg, 'data_nasc': nascimento, 'sexo': sexo}
setCadastros(superNovoCadastro)
atualizarCadastros(superNovoCadastro)
Upvotes: 1