Why is my onSubmit not working in PrimeReact Dialog? - reactjs

My code is no longer submitting data when onSubmit is pushed even though it was when I was using a and tag:
<Modal><Form onSubmit={ saveProject }></Form></Modal>
The only thing different now is I substituted Modal for as I am using PrimeReact and deleted the tag. Now it's no longer submitting data.
Can anyone tell me why it is no longer submitting the data to the backend?
/Projects.js
import React, { useState, useEffect } from "react";
import { Column } from "primereact/column";
import { DataTable } from "primereact/datatable";
import { Button } from "primereact/button";
// import { Modal, ModalFooter, ModalHeader } from "react-bootstrap";
import { InputText } from "primereact/inputtext";
import { InputTextarea } from "primereact/inputtextarea";
// import { InputNumber } from "primereact/inputnumber";
import { Dropdown } from "primereact/dropdown";
import { Dialog } from "primereact/dialog";
import axios from "axios";
const Projectz = () => {
const [ticket_title, setTicketTitle] = useState("");
const [ticket_description, setTicketDescription] = useState("");
// const [time_takes, setTimeTakes] = useState("");
const [type_menu, setTypeMenu] = useState("");
const [priority_menu, setPriorityMenu] = useState("");
const [status_menu, setStatusMenu] = useState("");
const [projects, setProjects] = useState([]);
//part of modal
const [displayResponsive, setDisplayResponsive] = useState(false);
// const [position, setPosition] = useState("center");
useEffect(() => {
getProjects();
}, []);
const getProjects = async () => {
const response = await axios.get("http://localhost:5002/ticket_table");
setProjects(response.data);
};
const saveProject = async (e) => {
e.preventDefault();
await axios.post("http://localhost:5002/ticket_table", {
ticket_title: ticket_title,
ticket_description: ticket_description,
// time_takes: time_takes,
type_menu: type_menu,
priority_menu: priority_menu,
status_menu: status_menu,
});
};
const dropdownValues1 = [{ value: "Issue" }, { value: "Bug" }, { value: "Error" }, { value: "Other" }];
const dropdownValues2 = [{ value: "Low" }, { value: "Medium" }, { value: "High" }, { value: "Immediate" }];
const dropdownValues3 = [{ value: "New" }, { value: "Open" }, { value: "In Progress" }, { value: "Resolved" }, { value: "Additional Info Required" }];
const dialogFuncMap = {
displayResponsive: setDisplayResponsive,
};
const onClick = (name, position) => {
dialogFuncMap[`${name}`](true);
};
const onHide = (name) => {
dialogFuncMap[`${name}`](false);
};
const renderFooter = (name) => {
return (
<div>
<Button label="Submit" className="p-button-rounded p-button-success mr-2 mb-2 success" />
</div>
);
};
// const [show, setShow] = useState(false);
// const handleClose = () => setShow(false);
// const handleShow = () => setShow(true);
return (
<>
<div className="grid table-demo">
<div className="col-12">
<div className="card">
<h5>Tickets</h5>
<div>
{/* <Button label="New Ticket" className="p-button-rounded mr-2 mb-2 npbutton" onClick={handleShow} /> */}
<Button className="p-button-rounded mr-2 mb-2 npbutton" label="New Ticket" onClick={() => onClick("displayResponsive")} />
</div>
<Dialog className="dialogModal" header="Create Ticket" visible={displayResponsive} onHide={() => onHide("displayResponsive")} breakpoints={{ "960px": "75vw" }} style={{ width: "30vw" }} footer={renderFooter("displayResponsive")}>
<form onSubmit={saveProject}>
<h5>Ticket Name</h5>
<InputText value={ticket_title} onChange={(e) => setTicketTitle(e.target.value)} type="text" placeholder="Enter ticket name"></InputText>
<h5>Ticket Description</h5>
<InputTextarea value={ticket_description} onChange={(e) => setTicketDescription(e.target.value)} type="text" placeholder="Enter ticket description" autoResize rows="3" cols="30" />
{/* <h5>Time Estimate (Hours)</h5> */}
{/* <InputNumber value={time_takes} onValueChange={(e) => setTimeTakes(e.value)} showButtons mode="decimal"></InputNumber> */}
<h5>Type</h5>
<Dropdown value={type_menu} onChange={(e) => setTypeMenu(e.value)} options={dropdownValues1} optionLabel="value" placeholder="Select" />
<h5>Priority</h5>
<Dropdown value={priority_menu} onChange={(e) => setPriorityMenu(e.value)} options={dropdownValues2} optionLabel="value" placeholder="Select" />
<h5>Status</h5>
<Dropdown value={status_menu} onChange={(e) => setStatusMenu(e.value)} options={dropdownValues3} optionLabel="value" placeholder="Select" />
</form>
</Dialog>
<div>
<DataTable
// sortMode="single" sortField="representative.name"
sortOrder={1}
scrollable
scrollHeight="400px"
responsiveLayout="scroll"
>
<Column field="ticket_title" header="Ticket Title" style={{ minWidth: "200px" }}></Column>
<Column field="description" header="Description" style={{ minWidth: "350px" }}></Column>
<Column field="status" header="Status" style={{ minWidth: "200" }}></Column>
<Column field="createdAt" header="Date" style={{ minWidth: "200px" }}></Column>
</DataTable>
</div>
</div>
</div>
</div>
<div className="grid table-demo">
<div className="col-12">
<div className="card">
<h5>Ticket Info</h5>
<div>
<DataTable
// value={projects}
// sortMode="single" sortField="representative.name"
// sortOrder={1}
// scrollable
// scrollHeight="400px"
// responsiveLayout="scroll"
>
{projects.map((project, index) => (
<tr key={project.id}>
<td>{index + 1}</td>
<td>{project.ticket_title}</td>
<td>{project.ticket_description}</td>
{/* <td>{ticket.time_takes}</td> */}
<td>{project.type_menu}</td>
<td>{project.priority_menu}</td>
<td>{project.status_menu}</td>
</tr>
))}
</DataTable>
</div>
</div>
</div>
</div>
</>
);
};
export default React.memo(Projectz);

This is because the Dialog renders renderFooter outside of your <form>. I ran into the same issue.
You can fix it instead of using the footer just rendering your button to look like its in the footer.
<Dialog className="dialogModal" header="Create Ticket" visible={displayResponsive} onHide={() => onHide("displayResponsive")} breakpoints={{ "960px": "75vw" }} style={{ width: "30vw" }}>
<form onSubmit={saveProject}>
....
<div className="p-dialog-footer pb-0">
<Button label="Submit" type="submit" className="p-button-rounded p-button-success mr-2 mb-2" />
</div>
</form>
</Dialog>

Related

Directus and React data not submitting to API

I'm trying to submit reviews to a directus app but the review is not getting added to the data.
I can retrieve the data but cannot add.
I've checked all permissions and set the directus app to public permissions.
cannot figure out what the problem could be.
can anyone advise what could be wrong?
the api call:
import axios from 'axios';
const url = 'https://pwsbbqhj.directus.app/items/Reviews';
export const readReviews = () => axios.get(url);
export const createReview = (newReview) => axios.post(url, newReview);
the data retrieval :
import React, { useState, useEffect } from 'react';
import * as api from '../../../api';
import { FaStar } from 'react-icons/fa';
const colors = {
orange: '#e42320',
grey: '#a9a9a9',
};
function Ratings() {
const stars = Array(5).fill(0);
const [currentValue, setCurrentValue] = React.useState(0);
const [hoverValue, setHoverValue] = React.useState(undefined);
const handleClick = (value) => {
setCurrentValue(value);
};
const handleMouseOver = (value) => {
setHoverValue(value);
};
const [review, setReview] = useState({});
const [reviews, setReviews] = useState([]);
useEffect(() => {
const fetchData = async () => {
const result = await api.readReviews();
setReviews(result.data.data);
};
fetchData();
}, []);
const createReview = async (review) => {
try {
const data = await api.createReview({ review });
setReview([...reviews, data.data]);
} catch (error) {
console.log(error);
}
};
let [reviewCount, setreviewCount] = useState([]);
const setCountFxn = (no) => {
setReview(no);
console.log(no);
};
return (
<div className='col-md-12 row-testimonials'>
<div className='reviews-heading pb-5 pt-5'>
<h2>REVIEWS FROM OUR CUSTOMERS</h2>
</div>
<div
className='themesflat-carousel-box has-bullets bullet-circle has-buttons has-arrows clearfix'
data-gap={30}
data-column={3}
data-column2={2}
data-column3={1}
data-auto='false'
>
<div className='owl-carousel owl-theme'>
{reviews.map((review) => (
<div className='themesflat-testimonials style-2 align-center clearfix' key={review.id}>
<div className='testimonial-item'>
<div className='inner'>
<div className='thumb'>
<img src='assets/img/testimonials/customer-1-90x90.jpg' alt='altimage' />
</div>
<blockquote className='text'>
<div className='name-pos clearfix'>
<h6 className='name'>{review.Title}</h6>
<span className='position'></span>
</div>
<p>{review.Body}</p>
<div className='list-star'>
{Array.from({ length: review.Rating }).map((i) => (
<FaStar key={i} size={18} color={colors.orange} />
))}
</div>
<div className='m-2'>
By: <span className='name'>{review.Name}</span>
</div>
</blockquote>
</div>
</div>
</div>
))}
</div>
</div>
<div className='bg-black'>
<form>
<div className='mb-5'>
<h2>RATE OUR SERVICE</h2>
<div className='mt-5 mb-5'>
{stars.map((_, index) => {
return (
<FaStar
key={index}
size={20}
style={{
marginRight: 10,
cursor: 'pointer',
}}
color={(hoverValue || currentValue) > index ? colors.orange : colors.grey}
onClick={() => {
setReview({ ...review, Rating: index + 1 });
}}
onMouseOver={() => handleMouseOver(index + 1)}
/>
);
})}
</div>
<div id='message'></div>
<div>
<input
type='text'
placeholder='Your Name'
required
value={review.Name}
onChange={(e) => setReview({ ...review, Name: e.target.value })}
className='wpcf7-form-control'
/>
</div>
<div>
<input
type='text'
placeholder='Review Title'
required
value={review.Title}
onChange={(e) => setReview({ ...review, Title: e.target.value })}
className='wpcf7-form-control'
/>
</div>
<textarea
placeholder='Your comment'
required
value={review.Body}
onChange={(e) => setReview({ ...review, Body: e.target.value })}
className='wpcf7-form-control'
/>
<button type='submit' className='submit wpcf7-form-control wpcf7-submit' onClick={createReview}>
submit
</button>
</div>
</form>
</div>
<div className='themesflat-spacer clearfix' data-desktop={80} data-mobile={60} data-smobile={60} />
</div>
);
}
export default Ratings;

When clicking on a row in the table, I need to open a modal, but how?

I use React with DataTable Component.
This is the library: https://www.npmjs.com/package/react-data-table-component#conditional-style-object
Here is my data table component:
import React, { useState, useEffect } from "react";
import EquipmentService from './EquipmentService';
import DataTable, { createTheme } from 'react-data-table-component';
import DataTableExtensions from "react-data-table-component-extensions";
import "react-data-table-component-extensions/dist/index.css";
import Downshift from 'downshift';
import { useCombobox } from 'downshift'
//Pacotes de import para os botoes de filtrar tabelas
import { purple } from '#material-ui/core/colors';
import FormGroup from '#material-ui/core/FormGroup';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Switch from '#material-ui/core/Switch';
import { withStyles } from '#material-ui/core/styles';
// reactstrap
import {
Card,
CardHeader,
Container,
Row,
} from "reactstrap";
import Header from "components/Headers/Headerfor.js";
import EditEquipment from "./EditEquipment";
import DeleteEquipment from "./DeleteEquipment";
import CreateEquipment from "./CreateEquipment";
const items = ['apple', 'pear', 'orange', 'grape', 'banana']
function ListEquipments() {
const [equipment, setEquipment] = useState([]);
useEffect(() => {
EquipmentService.getEquipment().then(res => setEquipment(res.data));
}, []);
//Estilo dos botoes de filtrar colunas
const PurpleSwitch = withStyles({
switchBase: {
color: purple[300],
'&$checked': {
color: purple[500],
},
'&$checked + $track': {
backgroundColor: purple[500],
},
},
checked: {},
track: {},
})(Switch);
const [state, setState] = React.useState({
ID: false,
Denominação: false,
Fabricante: false,
});
const handleChange = (event) => {
setState({ ...state, [event.target.name]: event.target.checked });
};
// FIM dos botoes
// tema da tabela, preciso colocar em outline para aplicar a todas.
const customStyles = {
rows: {
style: {
backgroundColor: '',
}
},
headCells: { //titulo da tabela.
style: {
paddingLeft: '8px', // override the cell padding for head cells
paddingRight: '8px',
backgroundColor: '#f6f9fc',
border: '1px solid #e5e5e5',
},
},
cells: {
style: {
paddingLeft: '8px', // override the cell padding for data cells
paddingRight: '8px',
borderLeft: '1px solid #e5e5e5',
},
},
};
const columns = [
/* {
name: 'ID',
selector: 'ID',
sortable: true,
omit: state.ID,
}, */
{
name: 'Código',
selector: 'codigo',
sortable: true,
grow: -1, //aumentar e diminuir o tamanho da coluna.
center: true, // centralizar a informação.
},
{
name: "Área",
selector: "area",
sortable: true,
//omit: state.Denominação,
},
{
name: "Setor Instalado",
selector: "setor",
sortable: true,
//omit: state.Denominação,
},
{
name: "Sistema",
selector: "sistema",
sortable: true,
//omit: state.Fabricante,
},
{
name: "Equipamento",
selector: "denominacao",
sortable: true,
},
{
name: "Fabricante",
selector: "fabricante",
sortable: true,
},
{
name: "Modelo de Equipamento",
selector: "modelo",
sortable: true,
},
];
const TranslateOptions = {
rowsPerPageText: 'Equipamentos por Página:',
rangeSeparatorText: 'de',
selectAllRowsItem: true,
selectAllRowsText: 'Todos',
}
const [inputItems, setInputItems] = useState(items)
const {
isOpen,
getToggleButtonProps,
getLabelProps,
getMenuProps,
getInputProps,
getComboboxProps,
highlightedIndex,
getItemProps,
} = useCombobox({
items: inputItems,
onInputValueChange: ({ inputValue }) => {
setInputItems(
items.filter(item =>
item.toLowerCase().startsWith(inputValue.toLowerCase()),
),
)
},
})
return (
<>
<Header />
{/* Page content */}
<Container className="mt--7" fluid>
{/* Table */}
<Row>
<div className="col">
<Card className="shadow">
<CardHeader className="border-0">
<h3 className="mb-0">Gestão de Equipamentos</h3>
{/* <FormGroup>
<FormControlLabel
control={<PurpleSwitch checked={state.ID} onChange={handleChange} name="ID" />}
label="ID"
/>
<FormControlLabel
control={<PurpleSwitch checked={state.Denominação} onChange={handleChange} name="Denominação" />}
label="Denominação"
/>
<FormControlLabel
control={<PurpleSwitch checked={state.Fabricante} onChange={handleChange} name="Fabricante" />}
label="Fabricante"
/>
</FormGroup> */}
<CreateEquipment />
</CardHeader>
<DataTableExtensions
columns={columns}
filterPlaceholder="Buscar"
filterHidden={false}
data={equipment.map((row) => ({
codigo: row.descricao,
area: row.area,
setor: row.setor_instalado,
sistema: row.sistema,
denominacao: row.denominacao,
fabricante: row.fabricante,
modelo: row.modelo,
//Status: row.status,
//Editar: <EditEquipment actual_id={row._id} />,
//Apagar: <DeleteEquipment actual_id={row._id} />,
}))}
>
<DataTable
noHeader
defaultSortField="id"
defaultSortAsc={false}
pagination
striped // sombra sim, sombra não.
responsive
highlightOnHover
onRowClicked={(row) => console.log(row.ID)}
//onRowClicked={EditEquipment}
customStyles={customStyles}
paginationComponentOptions={TranslateOptions}
/>
</DataTableExtensions>
</Card>
</div>
</Row>
</Container>
</>
);
};
in component: Data Table, i have: onRowClicked={(row) => console.log(row.ID)}
I need to click on a line and the modal appears.
This is the modal component, in a button.
function EditEquipment(props) {
const {
buttonLabel,
className,
actual_id,
} = props;
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
const [area, setArea] = useState('');
const [denominacao, setDenominacao] = useState('');
const [descricao, setDescricao] = useState('');
const [fabricante, setFabricante] = useState('');
const [modelo, setModelo] = useState('');
const [sistema, setSistema] = useState('');
const [setor_instalado, setSetor_instalado] = useState('');
const handleSubmit = (evt) => {
evt.preventDefault();
//alert(`Submitting Name ${firstName} ${lastName}`);
//resetFirstName();
//resetLastName();
}
const update = (evt) => {
let equipments = {area: area, denominacao: denominacao, descricao: descricao, fabricante: fabricante, modelo: modelo, setor_instalado: setor_instalado};
console.log(equipments)
EquipmentService.updateEquipment(equipments, actual_id).then(res =>{ //equipment._id no lugar do ID
console.log(res);
setModal(!modal);
//console.log("Etapa 4");
window.location.reload();
console.log("Etapa 5");
}).catch(error => console.log(error.response));
}
useEffect(() => {
async function getEquipment(){
EquipmentService.getEquipmentById(actual_id).then( (res) =>{
let equipments = res.data;
setArea(equipments.area); //equipments.tag
setDenominacao(equipments.denominacao);
setDescricao(equipments.descricao);
setFabricante(equipments.fabricante);
setSistema(equipments.sistema);
setModelo(equipments.modelo);
setSetor_instalado(equipments.setor_instalado);
});
}
getEquipment();
}, []);
return (
<div>
<Button color="success" size="sm" className="" onClick={toggle}> Editar </Button>
<Modal isOpen={modal} toggle={toggle} size="lg" className="mr-0 mt--1 mb--1">
<ModalHeader toggle={toggle}>Editar Equipamento </ModalHeader>
<ModalBody>
<form onSubmit={handleSubmit}>
<div className = "form-group">
<label> Área: </label>
<input name="tag" className="form-control"
value={area}
onChange={e => setArea(e.target.value)}
/>
</div>
<div className = "form-group">
<label> Setor Instalado: </label>
<input name="setor_instalado" className="form-control"
value={setor_instalado}
onChange={e => setSetor_instalado(e.target.value)}
/>
</div>
<div className = "form-group">
<label> Sistema: </label>
<input name="sistema" className="form-control"
value={sistema}
onChange={e => setSistema(e.target.value)}
/>
</div>
<div className = "form-group">
<label> Equipamento: </label>
<input name="equipamento" className="form-control"
value={denominacao}
onChange={e => setDenominacao(e.target.value)}
/>
</div>
<div className = "form-group">
<label> Código do Equipamento: </label>
<input name="Código" className="form-control"
value={descricao}
onChange={e => setDescricao(e.target.value)}
/>
</div>
<div className = "form-group">
<label> Fabricante: </label>
<input name="setor_instalado" className="form-control"
value={fabricante}
onChange={e => setFabricante(e.target.value)}
/>
</div>
<div className = "form-group">
<label> Modelo: </label>
<input name="modelo" className="form-control"
value={modelo}
onChange={e => setModelo(e.target.value)}
/>
</div>
</form>
<div className = "form-group">
<Card className=" shadow-lg bg-default">
<CardHeader className="">
<Row>
<Col>
<h4> QR Code: </h4>
</Col>
<Col>
</Col>
<Col >
<Button color="default" size="sm" className="ml-9" type="button">
Imprimir
</Button>
</Col>
</Row>
</CardHeader>
<CardBody>
<Row>
<Col className="">
<QRCode position="" value="http://www.darwinx.com.br" />
</Col>
<Col className="ml--6 pr-9 text-white">
<label> Número:</label> <br></br>
<label> Equipamento:</label> <br></br>
<label> Descrição:</label>
</Col>
<Col></Col>
</Row>
</CardBody>
</Card>
</div>
<Button color="success" onClick={update} >Atualizar</Button>{' '}
<Button color="secondary" onClick={toggle}>Cancelar</Button>
</ModalBody>
<ModalFooter>
</ModalFooter>
</Modal>
</div>
);
}
please someone help me?
ps: sorry for my english, i not speak english, and i use the google tradutor for need help.
Add the modal inside the return of the data table component. Add these on your data table component as well:
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
Then you can do:
onRowClicked={(row) => setModal(true)}
You should also probably store the currently selected equipment using a state hook. And make the modal read from it.

React prop value changing though it is readonly

I have a parent component - RoomSettings.tsx where I am passing a prop, room to a child component RoomSettingsStreams
RoomSettings.tsx
export default function RoomSettings() {
const { id } = useParams() as { id: string };
const [room, setRoom] = useState<Room | null>({
streams: [
{
name: "Somthing",
other: "Others",
},
{
name: "Somtehing 2",
others: "Sasdfasd",
},
],
});
return (
<div className="h-screen flex overflow-hidden bg-slate">
<RoomSettingsStreams initStreams={room ? [...room.streams] : []} />
</div>
);
}
RoomSettingStreams.tsx
interface RoomSettingsStreamsProps {
initStreams: Stream[] | null;
}
interface Stream {
name: string;
other: string;
}
export default function RoomSettingsStreams({
initStreams,
}: RoomSettingsStreamsProps) {
const [init, setInit] = useState<Stream[]>([]);
const [streams, setStreams] = useState<Stream[]>([]);
const [token, setToken] = useState("");
const [edit, setEdit] = useState(false);
const [message, setMessage] = useState({
message: "",
show: false,
type: "error",
});
const editRoom = () => {};
useEffect(() => {
if (initStreams) {
setStreams([...initStreams]);
setInit([...initStreams]);
}
}, [initStreams]);
return (
<div className="bg-card rounded-lg border border-gray-800">
{streams.map((e, i) => {
return (
<div className="p-6 pb-10 sm:mt-5 space-y-6 sm:space-y-5" key={i}>
<div className="flex">
<StreamLabel text={`Stream ${i + 1}`} />
</div>
{/* Item */}
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
<div>
<SettingsLabel text="Stream Title" />
</div>
<div className="mt-2 sm:mt-0 col-span-2">
{edit ? (
<Input
className="text-gray-200"
type="text"
placeholder="Enter stream title"
value={e.stream_title}
onChange={(f) => {
const newStreams = streams.map((e, j) => {
if (i === j) e.name = f.currentTarget.value;
return e;
});
setStreams([...newStreams]);
}}
/>
) : (
<p className="text-gray-200">{e.name}</p>
)}
</div>
<div className="mt-1 sm:mt-0 sm:col-span-2"></div>
</div>
{/* Item */}
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
<div>
<SettingsLabel text="Publishing Method" />
</div>
<div className="mt-2 sm:mt-0 col-span-2">
{edit ? (
<Listbox
options={["OBS-WebRTC", "Browser", "RTMP"]}
selected={e.other}
setSelected={(f: any) => {
const newStreams = streams.map((e, j) => {
if (i === j) e.other = f;
return e;
});
setStreams([...newStreams]);
}}
/>
) : (
<p className="text-gray-200">{e.publishing_method}</p>
)}
</div>
{/* OBS-WebRTC Keys */}
<SettingsLabel text="OBS Stream Name" />
<div className="mt-1 sm:mt-0 sm:col-span-2">
<InputClipboard
className="text-blue-brand"
type="text"
placeholder=""
value={e.name}
onClick={() => {
navigator.clipboard.writeText(e.name);
}}
readOnly={true}
/>
</div>
</div>
</div>
);
})}
<div className="p-6">
<AddItem text="Add another stream" />
</div>
<RoomSettingsEditButton
edit={edit}
setEdit={setEdit}
onCancel={() => {
setEdit(false);
if (!init) return;
setStreams([...init]);
}}
onSuccess={async () => {
editRoom();
setEdit(false);
}}
/>
</div>
);
}
When I am calling setStreams in RoomSettingsStreams.tsx it changes the value of the prop initStreams as well as the state variable init. I am using the spread operator so that there is no referential equality and I have checked with streams === initStreams which returns false but still the change in streams is reflected in the initStreams prop, any ideas how can I prevent it and what am I doing wrong?

How do I make the invalid hook call go away?

I get this error when trying to npm start my project:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
import React, { useState, useEffect } from 'react';
import './index.css';
import conspireLogo from './conspireLogo.png';
import Post from './Post'
import { auth, db } from './firebase';
import { makeStyles } from '#material-ui/core/styles';
import Modal from '#material-ui/core/Modal';
import { Button, Input } from '#material-ui/core'
import ImageUpload from './imageUpload';
//import { BrowserRouter, Route, Switch } from 'react-router-dom';
function getModalStyle() {
const top = 50;
const left = 50;
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`,
};
}
const useStyles = makeStyles((theme) => ({
paper: {
position: 'absolute',
width: 400,
backgroundColor: theme.palette.background.paper,
border: '2px solid #000',
boxShadow: theme.shadows[5],
padding: theme.spacing(2, 4, 3),
},
}));
function MainPage() {
const classes = useStyles();
const [modalStyle] = useState(getModalStyle);
const [posts, setPosts] = useState([]);
const [open, setOpen] = useState(false);
const [openSignIn, setOpenSignIn] = useState(false);
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [email, setEmail] = useState('');
const [user, setUser] = useState(null);
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((authUser) => {
if (authUser) {
console.log(authUser);
setUser(authUser);
} else {
setUser(null);
}
})
return () => {
unsubscribe();
}
}, [user,username]);
useEffect(() => {
db.collection('posts').orderBy('timestamp', 'desc').onSnapshot(snapshot => {
setPosts(snapshot.docs.map(doc => ({
id: doc.id,
post: doc.data()
})));
})
}, []);
const signUp = (event) => {
event.preventDefault();
auth
.createUserWithEmailAndPassword(email, password)
.then((authUser) => {
authUser.user.updateProfile({
displayName: username
})
})
.catch((error) => alert(error.message));
}
const signIn = (event) => {
event.preventDefault();
auth
.signInWithEmailAndPassword(email, password)
.catch((error) => alert(error.message));
setOpenSignIn(false);
}
return (
<div className="app">
<Modal
open={open}
onClose={() => setOpen(false)}
>
<div style={modalStyle} className={classes.paper}>
<form className="app__signup">
<center>
<img
className="app__headerImage"
src={conspireLogo}
alt="Conspire Logo"
/>
</center>
<Input
placeholder="username"
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<Input
placeholder="email"
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Input
placeholder="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<Button type="submit" onClick={signUp}>Sign Up</Button>
</form>
</div>
</Modal>
<Modal
open={openSignIn}
onClose={() => setOpenSignIn(false)}
>
<div style={modalStyle} className={classes.paper}>
<form className="app__signup">
<center>
<img
className="app__headerImage"
src={conspireLogo}
alt="Conspire Logo"
/>
</center>
<Input
placeholder="email"
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Input
placeholder="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<Button type="submit" onClick={signIn}>Sign In</Button>
</form>
</div>
</Modal>
<div className="app__header">
<img
className="app__headerImage"
src={conspireLogo}
alt="Conspire Logo"
/>
{user ? (
<Button onClick={() => auth.signOut()}>Logout</Button>
): (
<div className="app__loginContainer">
<Button onClick={() => setOpenSignIn(true)}>Sign In</Button>
<Button onClick={() => setOpen(true)}>Sign Up</Button>
</div>
)}
</div>
<div className="app__footer">
<Button onClick={() => setOpenSignIn(true)}><img
className="app__footerImage"
src="http://www.simpleimageresizer.com/_uploads/photos/bdfbb0d1/346a1f4363e1b59f6860fdce6abc1082_2_15.jpg"
alt="Create"
/>
</Button>
</div>
<div className="app__posts">
<div className="app__postsLeft">
{
posts.map(({id, post}) => (
<Post key={id} postId={id} user={user} username={post.username} caption={post.caption} imageUrl={post.imageUrl}></Post>
))
}
</div>
</div>
{user?.displayName ? (
<ImageUpload username={user.displayName} />
): (
<h3 className="center">Sorry you need to login to upload</h3>
)}
</div>
);
}
export default MainPage;
const [modalStyle] = useState(getModalStyle);
You're storing the function reference, not the function's return. Change it to
const [modalStyle] = useState(getModalStyle());
Moreover as you don't need to change this modalStyle, you don't need to have it in state
<div style={getModalStyle()} className={classes.paper}>
I don't think so there should be any error in this file, please check the other files
ex - Post, ImageUpload

How to add data into an array using inputs in reactjs?

I am new to react and I am trying to build a todo app which basically can execute the CRUD operation. I am able to update and delete as of now. But not sure how to create an object and save it into the array.
When i click on edit or add task button a modal pop up and i am trying to enter the title and description value there.
This is my Index.js file
import React, {Component} from 'react';
import { Button, Modal } from 'reactstrap';
import Modals from './Modals'
const todoItems = [
{
id: 1,
title: "Go to Market",
description: "Buy ingredients to prepare dinner",
completed: true
},
{
id: 2,
title: "Study",
description: "Read Algebra and History textbook for upcoming test",
completed: false
},
{
id: 3,
title: "Sally's books",
description: "Go to library to rent sally's books",
completed: true
},
{
id: 4,
title: "Article",
description: "Write article on how to use django with react",
completed: false
}
];
class Index extends Component {
state = {
modal: false,
items: todoItems,
selectedItem: null,
selectedIndex: -1,
}
toggle = (item, index) => {
if (item) {
this.setState({ selectedItem: item, selectedIndex: index })
}
this.setState({ modal: !this.state.modal });
};
handleChange = () => {
let oldState = this.state.items;
this.setState({ items: oldState })
}
onDelete = (item) => {
const newData = this.state.items.filter(i => i.title !== item.title)
this.setState({ items: newData })
}
render() {
return (
<>
<h1 className="p-3">TODO APP</h1>
<div style={{ backgroundColor: "white", padding: "50px", color: "black"}} className="container">
<div className="row">
<button className="btn btn-primary" onClick={() => this.toggle()}>Add task</button>
</div>
<div className="row my-5">
<Button color="danger mr-5">Incomplete</Button>
<Button color="success">Complete</Button>
<Modals index={this.state.selectedIndex} onDelete={this.onDelete} item={this.state.selectedItem} handleChange={this.handleChange} modal={this.state.modal} toggle={this.toggle} />
</div>
<hr/>
{this.state.items.map((item, index) => {
return(
<div key={item.id}>
<div className="row">
<p style={{ textAlign: "left" }}>{item.title}</p>
<Button onClick={() => this.toggle(item, index)} className="mr-0 ml-auto" color="info">Edit</Button>
<Button onClick={() => this.onDelete(item)} className="ml-5" color="warning">Delete</Button>
</div>
<hr/>
</div>
)
})}
</div>
</>
);
}
}
export default Index;
This is my modal.js file
import React, { useState, useEffect } from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
function Modals(props) {
const {
className,
buttonLabel,
handleChange,
item,
index,
toggle,
} = props;
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
useEffect(() => {
if (item && item.title){
setTitle(item.title)
setDescription(item.description)
}
}, [item])
const setValues = () => {
handleChange({ title: title, description: description });
props.toggle();
push({
})
}
return (
<div>
<Modal isOpen={props.modal} className={className} style={{ color: "black"}}>
<ModalHeader >Todo Item</ModalHeader>
<ModalBody>
<div className="container-fluid">
<div className="row mb-3">
<div className="col-12">
<p className="mb-0">Title</p>
</div>
<div className="col-12">
<input onChange={(e) => setTitle(e.target.value)} value={title} className="w-100" type="text" placeholder="Enter title"/>
</div>
</div>
<div className="row mb-3">
<div className="col-12">
<p className="mb-0">Description</p>
</div>
<div className="col-12">
<input type="text" onChange={(e) => setDescription(e.target.value)} value={description} className="w-100" placeholder="Enter Description"/>
</div>
</div>
<div className="row">
<div className="col-12">
<input type="checkbox"/>
<span className="ml-2"> Completed </span>
</div>
</div>
</div>
</ModalBody>
<ModalFooter>
<Button onClick={() => setValues()} color="success">Submit</Button>
<Button onClick={props.toggle} color="secondary">Cancel</Button>
</ModalFooter>
</Modal>
</div>
)
}
export default Modals;
Thanks in advance!!
One way would be to just create a method in index.js
addItem = (item) =>{
this.setState({items: [...this.state.items, item]})
}
and then just pass it as a prop to your Modal and call it in setValues,
const setValues = () => {
handleChange({ title: title, description: description });
props.toggle();
props.addItem({ title: title, description: description, //etc})
}

Resources