I have created a CRUD application and successfully it is performing all the operations.
But when I try to create a modal so that it shows up a warning either to delete the id or not on clicking delete. And If I try to delete a particular id from the modal I'm unable to delete the selected item, else it is deleted the latest id in the list.
What might be the problem that is making me not delete a particular id from the list only when creating a modal.
Help me how I can make it work.
This is the button to open the warning modal:
const [open, setOpen] = useState(false);
const toggle = () => setOpen(!open);
<button onClick={toggle}>
<MdIcons.MdDelete color='black' fontSize="1.3rem"/>delete</button>
This is the modal that opens after clicking delete:
<Modal isOpen={open} toggle={toggle}>
<ModalHeader toggle={toggle}>Warning</ModalHeader>
<ModalBody>Are you sure to delete this id from the list...</ModalBody>
<ModalFooter>
<Button onClick={() => onDelete(data.id)}>YES</Button>
<Button onClick={toggle}>Cancel</Button>
</ModalFooter>
</Modal>
In the above modal I have give the onclick event for button YES to delete the id selected, but the delete functionality is not working when I use it on a modal.
These are the button functionalities:
const getData = () => {
axios.get(`https://62c45bb0abea8c085a73b996.mockapi.io/Reactcrud`)
.then((getData) => {
setAPIData(getData.data);
})
}
const onDelete = (id) => {
axios.delete(`https://62c45bb0abea8c085a73b996.mockapi.io/Reactcrud/${id}`)
.then(() => {
getData();
})
}
Please help me how I can achieve the functionality of deleting the particular id after modal opens, and let me know if you need any more details regarding my code.
I am new to react, i don't know if my explanation will be correct, my theory is that the problem was this: You were rendering the modal for every record, and only the last modal remained.
I put the modal outside the loop, and i declared a useState to track the selected id to delete, it worked =D
Read.js :
import axios from "axios";
import React, { useEffect, useState } from "react";
import { Table, Button, List, Popup, Grid, Icon, Dropdown, Menu, Header } from "semantic-ui-react";
import { useNavigate, Link } from "react-router-dom";
import * as MdIcons from "react-icons/md";
import * as AiIcons from "react-icons/ai";
import * as FiIcons from "react-icons/fi";
import { Modal, ModalFooter, ModalHeader, ModalBody } from "reactstrap";
import SideMenu from "../SideMenu/SideMenu";
function Read() {
const [APIData, setAPIData] = useState([]);
const [idToDelete, setIdToDelete] = useState(0);
useEffect(() => {
axios.get(`https://62c45bb0abea8c085a73b996.mockapi.io/Reactcrud`).then((response) => {
console.log(response.data);
setAPIData(response.data);
});
}, []);
const setData = (data) => {
let {
id,
image,
companyName,
email,
companyNumber,
uniqueNumber,
lineofBusiness,
companyRevenue,
openingTime,
closingTime,
discount,
rating,
address1,
address2,
pincode,
area,
city,
state,
country,
} = data;
localStorage.setItem("ID", id);
localStorage.setItem("Image", image);
localStorage.setItem("Email", email);
localStorage.setItem("Company Name", companyName);
localStorage.setItem("Company Number", companyNumber);
localStorage.setItem("Unique Number", uniqueNumber);
localStorage.setItem("Line of Business", lineofBusiness);
localStorage.setItem("Company Revenue", companyRevenue);
localStorage.setItem("Opening Time", openingTime);
localStorage.setItem("Closing Time", closingTime);
localStorage.setItem("Discount", discount);
localStorage.setItem("Rating", rating);
localStorage.setItem("Address1", address1);
localStorage.setItem("Address2", address2);
localStorage.setItem("Pincode", pincode);
localStorage.setItem("Area", area);
localStorage.setItem("City", city);
localStorage.setItem("State", state);
localStorage.setItem("Country", country);
};
const getData = () => {
axios.get(`https://62c45bb0abea8c085a73b996.mockapi.io/Reactcrud`).then((getData) => {
setAPIData(getData.data);
});
};
const onDelete = () => {
axios
.delete(`https://62c45bb0abea8c085a73b996.mockapi.io/Reactcrud/${idToDelete}`)
.then(() => {
navigate("/company/list");
toggle();
})
.then(() => {
getData();
});
};
let navigate = useNavigate();
const addUser = () => {
navigate("/company/create");
};
const [open, setOpen] = useState(false);
const toggle = () => setOpen(!open);
const [search, setSearch] = useState("");
return (
<>
<div className="container-fluid">
<div className="row">
<div className="col-lg-12" style={{ marginLeft: "-11px" }}>
<SideMenu />
</div>
</div>
<div className="row">
<div className="col-lg-3"></div>
<div className="col-lg-6">
<Button primary style={{ width: "150px", height: "40px" }} onClick={addUser}>
Add Company
</Button>
<input
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search by any Category"
style={{
position: "absolute",
width: "260px",
height: "40px",
marginLeft: "285px",
border: "none",
fontSize: "15px",
padding: "8px",
borderRadius: "20px 20px 20px 20px",
}}
/>
<table style={{ width: "700px", height: "200px" }}>
<thead style={{ margin: "50px" }}>
<tr>
<th style={{ textAlign: "center" }}>List of Companies</th>
</tr>
</thead>
{APIData.filter((data) =>
Object.values(data).some((value) => value.toLowerCase().includes(search.toLowerCase()))
).map((data, id) => {
return (
<>
<tbody key={id}>
<li
style={{
minHeight: "140px",
borderRadius: "5px",
margin: "20px 0px",
listStyle: "none",
padding: "25px",
backgroundColor: "white",
boxShadow: "0 0 20px 0px rgba(0,0,0,0.2)",
}}
>
<tr>
<Link to="/company/view">
<button
style={{
background: "transparent",
border: "none",
color: "blue",
}}
onClick={() => setData(data)}
>
{data.companyName}
</button>
</Link>
</tr>
<tr>{data.companyNumber}</tr>
<tr>{data.uniqueNumber}</tr>
<tr>{data.lineofBusiness}</tr>
</li>
<div
style={{
position: "absolute",
marginLeft: "580px",
marginTop: "-120px",
}}
>
<Dropdown
icon={
<AiIcons.AiOutlineEllipsis
style={{
color: "black",
fontSize: "1.3rem",
marginTop: "15px",
marginLeft: "30px",
border: "1px solid black",
width: "30px",
height: "30px",
borderRadius: "50%",
}}
/>
}
pointing="top right"
>
<Dropdown.Menu>
<Dropdown.Item icon="edit" text="Edit">
<Link to="/company/edit">
<button
onClick={() => setData(data)}
style={{
background: "transparent",
border: "none",
}}
>
<FiIcons.FiEdit color="black" fontSize="1.3rem" /> Edit
</button>
</Link>
</Dropdown.Item>
<Dropdown.Item icon="delete" text="Delete">
<button
onClick={() => {
setIdToDelete(data.id);
toggle();
}}
style={{
background: "transparent",
border: "none",
}}
color="red"
>
<MdIcons.MdDelete color="black" fontSize="1.3rem" />
delete
</button>
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</div>
</tbody>
</>
);
})}
</table>
<Modal isOpen={open} toggle={toggle}>
<ModalHeader toggle={toggle}>Warning</ModalHeader>
<ModalBody>Are you sure to delete this id from the list...</ModalBody>
<ModalFooter>
<Button color="red" onClick={onDelete}>
Okay
</Button>
<Button color="primary" onClick={toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</div>
</div>
</div>
</>
);
}
export default Read;
Related
Quantity component is my child class and Mainpart component is my parent class.i want to use my (count) in my parent class.but i dont know how to pass that data.sorry my english is not good.i think you will get the idea.
const MainPart = () => {
const submit = (event) => {
debugger;
event.preventDefault();
}
return (
<div>
<form onSubmit={submit}>
<Container>
<Row>
<Col sm={4}>
<Picture image='../images/test.jpg' alt='tent' />
</Col>
<Col sm={8}>
<Title title='4 Person tent' itemNo='Item No. MA000001' />
<Currency mark='$' price='150.00' />
<Quantity />
<div style={{ marginTop: '5%', textAlign: 'center' }}>
<input type='submit' value='ADD TO CART' style={{ backgroundColor: 'yellow', padding: '5px 5px 5px 5px' }} />
</div>
</Col>
</Row>
</Container>
</form>
</div>
);
};
--------------------------------------------------------------------------------------------------
const Quantity = (props) => {
const [count, setCount] = useState(0);
const increaseClick = () => {
setCount(count + 1 )
}
const decreaseClick = () => {
setCount(count - 1 )
}
return (
<>
<div style={{ display: 'flex', marginTop: '5%', marginLeft: '30%' }}>
<Button variant="primary" style={{ marginRight: '5%' }} onClick={decreaseClick}>-</Button>
<h3>{count}</h3>
<Button variant="primary" style={{ marginLeft: '5%' }} onClick={increaseClick}>+</Button>
</div>
</>
);
};
You have to create your state in parent and then pass to child, it will work.
const MainPart = () => {
const [count, setCount] = useState(0);
return (
...Your rest of code.
<Quantity count={count} setCount={setCount} />
)
}
Then In your child component, Use like this:
const Quantity = ({ count, setCount }) => {
const increaseClick = () => {
setCount(count + 1 )
}
const decreaseClick = () => {
setCount(count - 1 )
}
return (
<>
<div style={{ display: 'flex', marginTop: '5%', marginLeft: '30%'
}}>
<Button variant="primary" style={{ marginRight: '5%' }} onClick={decreaseClick}>-</Button>
<h3>{count}</h3>
<Button variant="primary" style={{ marginLeft: '5%' }} onClick={increaseClick}>+</Button>
</div>
</>
);
}
I want to open a pop-up-like component 'ViewDownload.js' when I click on the Download Button that is present in a cell in the Data Grid of Material-UI.
Can someone please help me with how I can achieve this?
When I click on the Download button, it should open a new Component on top of the present screen(like a pop-up).
import React from 'react';
import { DataGrid } from '#mui/x-data-grid';
import Button from '#mui/material/Button';
import { Box, Typography } from '#mui/material';
import ViewDownload from './ViewDownload';
const columns = [
{ field: 'id', headerName: 'SL. No', width: 70, headerClassName: 'super-app-theme--header' },
{ field: 'status', headerName: 'PO Status', width: 80, headerClassName: 'super-app-theme--header' },
{
field: 'action',
headerName: 'Action',
type: 'file',
width: 120,
headerClassName: 'super-app-theme--header',
cellClassName: 'super-app-theme--cell',
renderCell: (params) => (
<strong>
<Button variant="contained" size="small" onClick={() => <ViewDownload />}>
Download
</Button>
{/* {isShown && <ViewDownload />} */}
</strong>
)
// renderCell: renderDetailsButton
}
];
const rows = [
{
id: 1,
poNo: 'PO_CCTN_0822_001',
poDate: '01/08/2022',
from: '08/2022',
to: '09/2022',
state: 'TN',
product: 'MLP',
certificate: 'Document',
quantity: '8000',
status: 'PENDING',
action: 'View/Download'
}
];
const Document = () => {
return (
<>
<Typography variant="h2" color="gray">
Documents
</Typography>
<Button variant="contained" sx={{ my: 3, background: 'gray', px: 3, py: 0 }}>
Filter
</Button>
<Box
display="flex"
justifyContent="center"
alignItems="center"
minHeight="100vh"
flexDirection="column"
sx={{
mt: -18,
mx: -14,
'& .super-app-theme--header': {
backgroundColor: 'gray',
color: 'white'
},
'& .super-app-theme--cell': {
color: '#86C029',
cursor: 'pointer'
}
}}
>
<Box sx={{ height: 300, width: { xs: '60%', sm: '65%', md: '80%' } }}>
<DataGrid rows={rows} columns={columns} pageSize={5} rowsPerPageOptions={[5]} />
</Box>
</Box>
</>
);
};
export default Document;
Seperate component (Eg: ViewButton.jsx)
function ViewButton(){
const [show, setShow] = useState(false);
return (
<>
// button component, onClick = setShow(true)
{ show && (<ViewDownload />) }
</>
)
}
Now you can call this component in renderCell method
You need create Modal component and ModalButton component.
function Modal({ children }) {
return ReactDOM.createPortal(children, document.body);
}
function ModalButton(props) {
const [visible, setVisible] = React.useState(false);
return (
<div>
<button variant="contained" size="small" onClick={() => setVisible(true)}>
View download
</button>
{visible && (
<Modal>
<div className="overlay" style={{position: "fixed", inset: "0 0 0 0"}}></div>
<div
style={{
top:"30%",
left: "30%",
position: "fixed",
width:"300px",
height: "300px",
backgroundColor: "rgba(0, 0, 0, 0.5)"
}}
>
<div style={{textAlign: "right"}}>
<button style={{width: "100px"}} onClick={() => setVisible(false)}>Close</button>
</div>
<h1>Modal content</h1>
</div>
</Modal>
)}
</div>
);
}
You change ModalButton to Button in renderCell
you can review here
I have simple modal using material ui 'Modal', i want to make it draggable, so user could move modal whereever they want simply by dragging, so i used 'Draggable' from react draggable, but i'm getting this error: Warning: React does not recognize the PaperComponent prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase papercomponent instead. If you accidentally passed it from a parent component, remove it from the DOM element.
what am i doing wrong ?
codesandbox:
https://codesandbox.io/s/draggabledialog-material-demo-forked-srw9yn?file=/demo.js
code:
import * as React from "react";
import Button from "#mui/material/Button";
import { Modal, Box } from "#material-ui/core";
import { Close } from "#material-ui/icons";
import Paper from "#mui/material/Paper";
import Draggable from "react-draggable";
export default function DraggableDialog() {
const [open, setOpen] = React.useState(false);
function PaperComponent(props) {
return (
<Draggable
handle="#draggable-dialog-title"
cancel={'[class*="MuiDialogContent-root"]'}
>
<Paper {...props} />
</Draggable>
);
}
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="outlined" onClick={handleClickOpen}>
Open draggable dialog
</Button>
<Modal
open={open}
onClose={handleClose}
PaperComponent={PaperComponent}
// aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
aria-labelledby="draggable-dialog-title"
>
<div>
<form
style={{
width: "360px",
color: "white",
display: "flex",
flexDirection: "column",
backgroundColor: "#1E2328"
}}
>
<div
style={{
backgroundColor: "black",
margin: "0",
display: "flex",
alignItems: "center",
height: "56px",
width: "360px",
color: "white",
justifyContent: "space-between"
}}
m={2}
>
<Box
style={{
color: "#E9ECEC",
fontSize: "21px"
}}
>
Countries{" "}
</Box>
<button
style={{ color: "white" }}
onClick={handleClose}
aria-label="close-settings-popup"
>
<Close />
</button>
</div>
<div style={{ height: "100%" }}>
<div>
Country Name
<p>Germany</p>
<p>France</p>
</div>
</div>
</form>
</div>
</Modal>
</div>
);
}
Modal component does not recognize PaperComponent that you passing to it as prop,
if you only want modal to be draggable modify your code like so:
import * as React from "react";
import Button from "#mui/material/Button";
import { Modal, Box } from "#material-ui/core";
import { Close } from "#material-ui/icons";
import Paper from "#mui/material/Paper";
import Draggable from "react-draggable";
export default function DraggableDialog() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="outlined" onClick={handleClickOpen}>
Open draggable dialog
</Button>
<Modal
open={open}
onClose={handleClose}
// aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
aria-labelledby="draggable-dialog-title"
>
<Draggable>
<div>
<form
style={{
width: "360px",
color: "white",
display: "flex",
flexDirection: "column",
backgroundColor: "#1E2328"
}}
>
<div
style={{
backgroundColor: "black",
margin: "0",
display: "flex",
alignItems: "center",
height: "56px",
width: "360px",
color: "white",
justifyContent: "space-between"
}}
m={2}
>
<Box
style={{
color: "#E9ECEC",
fontSize: "21px"
}}
>
Countries{" "}
</Box>
<button
style={{ color: "white" }}
onClick={handleClose}
aria-label="close-settings-popup"
>
<Close />
</button>
</div>
<div style={{ height: "100%" }}>
<div>
Country Name
<p>Germany</p>
<p>France</p>
</div>
</div>
</form>
</div>
</Draggable>
</Modal>
</div>
);
}
https://codesandbox.io/s/draggabledialog-material-demo-forked-sx2npc?file=/demo.js
I have a react component where I map through a list of clients and display each client in a card.
return (
<div className='VolunteerClientsTab'>
{volunteerClients && volunteerClients.map((client) => (
<React.Fragment key={client.id}>
<div className='VolunteerClientsTab__card'>
<Avatar style={{ alignSelf: 'center', marginTop: '.5rem' }}>{client.first_name[0]}{client.last_name[0]}</Avatar>
<h2>{client.first_name} {client.last_name}</h2>
<h4>Details</h4>
<p><AiOutlineMail style={iconStyles} /> {client.email}</p>
<p><AiOutlinePhone style={iconStyles} /> {formatPhoneNumber(client.contact_number)}</p>
<h4 style={{ marginTop: '1rem' }}>Actions</h4>
<p onClick={handleOpenClientNeedsModal} className='hover-underline'><BiDonateHeart style={iconStyles} />View Needs</p>
<p className='hover-underline'><HiOutlineDocumentReport style={iconStyles} />Write Report</p>
<p className='hover-underline'><FiVideo style={iconStyles} />Contact Client</p>
</div>
<ClientNeeds open={openClientNeedsModal} handleClose={handleCloseClientNeedsModal} client={client} />
</React.Fragment>
))}
</div>
)
};
ClientNeeds is a component that renders an MUI modal to display additional client information. I am passing it the client object within the loop but when I open the modal only the client of the last index in the volunteerClients array was passed to all the modal components. Does anyone have any idea why this is happening?
ClientNeeds component
import React from 'react';
import Box from '#mui/material/Box';
import Modal from '#mui/material/Modal';
import PropTypes from 'prop-types';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
const ClientNeeds = ({ open, handleClose, client }) => {
return (
<div>
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<h2>{client.email}</h2>
</Box>
</Modal>
</div>
)
};
ClientNeeds.propTypes = {
open: PropTypes.bool,
handleClose: PropTypes.func,
client: PropTypes.object
};
export default ClientNeeds;
MY SOLUTION
Passing the client onClick to an additional global state object and passing that state object to the modal,
const [selectedClient, setSelectedClient] = useState(null)
also only rendering the clientNeedsModal is there is an object in that state.
<div className='VolunteerClientsTab'>
{volunteerClients && volunteerClients.map((client) => (
<React.Fragment key={client.id}>
<div className='VolunteerClientsTab__card'>
<Avatar style={{ alignSelf: 'center', marginTop: '.5rem' }}>{client.first_name[0]}{client.last_name[0]}</Avatar>
<h2>{client.first_name} {client.last_name}</h2>
<h4>Details</h4>
<p><AiOutlineMail style={iconStyles} /> {client.email}</p>
<p><AiOutlinePhone style={iconStyles} /> {formatPhoneNumber(client.contact_number)}</p>
<h4 style={{ marginTop: '1rem' }}>Actions</h4>
<p onClick={() => handleOpenNeeds(client)} className='hover-underline'><BiDonateHeart style={iconStyles} />View Needs</p>
<p className='hover-underline'><HiOutlineDocumentReport style={iconStyles} />Write Report</p>
<p className='hover-underline'><FiVideo style={iconStyles} />Schedule Meeting</p>
</div>
{selectedClient ? (
<ClientNeeds open={openClientNeedsModal} handleClose={handleCloseClientNeedsModal} client={selectedClient} />
) : null}
</React.Fragment>
))}
</div>
const handleCloseClientNeedsModal = () => {
setSelectedClient(null)
setOpenClientNeedsModal(false);
}
const handleOpenNeeds = (client) => {
setSelectedClient(client)
handleOpenClientNeedsModal()
}
This allows me to pass any individual object within my array to the modal component as originally desired
In a React project, I've created Chat Section. All designing and functionalities done, except that when messages are sent it doesn't automatically scroll down. What could be the best possible solution?
Here is the code for reference
const MessageApp = () => {
const [textValue, setTextValue] = useState("");
const [textMessages, setTextMessages] = useState([]);
const [newTextValue, setNewTextValue] = useState("");
const [showSenderMessage, setShowSenderMessage] = useState(false);
const [showRecieverMessage, setShowRecieverMessage] = useState(false);
useEffect(() => {
const newData = localStorage.getItem("messages");
setTextMessages(newData);
}, []);
const sendMessage = (e) => {
e.preventDefault();
setShowSenderMessage(true);
if (textValue != "") {
setTextMessages([...textMessages, textValue]);
localStorage.setItem("messages", textMessages);
setTextValue("");
} else {
return;
}
};
return (
<>
{showSenderMessage &&
textMessages.map((text) => (
<div
className="bubble-sender"
style={{
display: "flex",
flexWrap: "wrap",
justifyContent: "flex-start",
width: "80%"
}}
>
<span style={{ width: "20%" }}>
<img
alt="blank profile"
src="https://cdn.business2community.com/wp-content/uploads/2017/08/blank-profile-picture-973460_640.png"
style={{
height: "50px",
width: "50px",
border: "2px solid black",
borderRadius: "50%"
}}
/>
</span>
<span style={{ width: "80%" }}>
{text}
<br />
<span
style={{
display: "flex",
flexWrap: "wrap",
justifyContent: "flex-end"
}}
>
<small style={{ color: "grey", float: "right" }}>
11:23 AM
</small>
</span>
</span>
</div>
))}
<span>
<form
style={{
position: "fixed",
bottom: "0",
marginBottom: "80px",
width: "100%"
}}
>
<div className="col-lg-10 mb-3">
<div className="input-group mycustom">
<input
value={textValue}
type="text"
required
placeholder="Send Message"
maxLength="30"
onChange={(e) => setTextValue(e.target.value)}
/>
<div className="input-group-prepend">
<button
type="submit"
style={{
color: "white",
display: "flex",
flexWrap: "wrap",
justifyContent: "space-evenly"
}}
onClick={sendMessage}
>
Send Message
</button>
</div>
</div>
</div>
</form>
</span>
</>
);
};
export default MessageApp;
Following is the codesandbox link: https://codesandbox.io/s/upbeat-montalcini-bpdsp
try this:
import React, { useState, useEffect, useRef } from "react";
import "./MessageApp.css";
const MessageApp = () => {
const [textValue, setTextValue] = useState("");
const [textMessages, setTextMessages] = useState([]);
const [newTextValue, setNewTextValue] = useState("");
const [showSenderMessage, setShowSenderMessage] = useState(false);
const [showRecieverMessage, setShowRecieverMessage] = useState(false);
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
};
useEffect(scrollToBottom, [textMessages]);
useEffect(() => {
const newData = localStorage.getItem("messages");
setTextMessages(newData.split(","));
}, []);
const sendMessage = (e) => {
e.preventDefault();
setShowSenderMessage(true);
if (textValue != "") {
// const newTextValueHere = textValue;
// setNewTextValue(newTextValueHere);
// setTextValue("");
setTextMessages(preVal=>[...preVal,textValue]);
localStorage.setItem("messages", textMessages);
setTextValue("");
} else {
return;
}
};
return (
<>
{showSenderMessage &&
textMessages.map((text) => (
<div
className="bubble-sender"
style={{
display: "flex",
flexWrap: "wrap",
justifyContent: "flex-start",
width: "80%"
}}
>
<span style={{ width: "20%" }}>
<img
alt="blank profile"
src="https://cdn.business2community.com/wp-content/uploads/2017/08/blank-profile-picture-973460_640.png"
style={{
height: "50px",
width: "50px",
border: "2px solid black",
borderRadius: "50%"
}}
/>
</span>
<span style={{ width: "80%" }}>
{text}
<br />
<span
style={{
display: "flex",
flexWrap: "wrap",
justifyContent: "flex-end"
}}
>
<small style={{ color: "grey", float: "right" }}>
11:23 AM
</small>
</span>
</span>
</div>
))}
<span>
<form
style={{
position: "fixed",
bottom: "0",
marginBottom: "80px",
width: "100%"
}}
>
<div className="col-lg-10 mb-3">
<div className="input-group mycustom">
<input
value={textValue}
type="text"
required
placeholder="Send Message"
maxLength="30"
onChange={(e) => setTextValue(e.target.value)}
/>
<div className="input-group-prepend">
<button
type="submit"
style={{
color: "white",
display: "flex",
flexWrap: "wrap",
justifyContent: "space-evenly"
}}
onClick={sendMessage}
>
Send Message
</button>
</div>
</div>
</div>
</form>
</span>
<div ref={messagesEndRef} />
</>
);
};
export default MessageApp;
here a sandbox based on yours ( I just remove commented code).
I have fixed a bug on your setTextMessages where the app return an iterator error.
You will need to make some style adjustment because for now the new message is "hide" under the input field.
UPDATE
your const newData is typeOf string so you need to split it in your `setTexMessage()` like this:
useEffect(() => {
const newData = localStorage.getItem("messages");
setTextMessages(newData.split(","));
}, []);