I have a function that updates the State values of chatId, currUser, and msg. This function is called twice, so I expect the values to be updated twice. However, the values are only updated once. What am I doing wrong?
This the function:
const displayMessage = (message) => {
const newMsg = { id: chatId, text: message, sender: currUser };
setChatId((prevId) => prevId + 1);
setCurrUser((prevUser) => {
return prevUser === "user" ? "bot" : "user";
});
console.log(`currUser: ${currUser}`);
setMsg((prevMsg) => [...prevMsg, newMsg]);
};
This function is being called in fetchApi() and handleSend().
This is the entire code:
import {
Box,
TextField,
Button,
Typography,
Avatar,
Grid,
Paper,
} from "@mui/material";
import SendIcon from "@mui/icons-material/Send";
import { useState, useEffect } from "react";
import axios from "axios";
const messages = [
{ id: 1, text: "Hi there!", sender: "bot" },
{ id: 2, text: "Hello!", sender: "user" },
{ id: 3, text: "How can I assit you today?", sender: "bot" },
];
function App() {
const [input, setInput] = useState("");
const [msg, setMsg] = useState(messages);
const [chatId, setChatId] = useState(4);
const [currUser, setCurrUser] = useState("user");
const fetchApi = async () => {
try {
const response = await axios.get(
`https://www.omdbapi.com/?apikey=213f50cd&t=${input}`
);
displayMessage(response.data.Plot);
} catch (error) {
console.error(error);
}
};
const handleSend = () => {
if (input.trim() !== "") {
console.log(`user input: ${input}`);
// setCurrUser(currUser === "user" ? "bot" : "user");
// setCurrUser((prevUser) => (prevUser === "user" ? "bot" : "user"));
displayMessage(input);
fetchApi();
}
};
const displayMessage = (message) => {
const newMsg = { id: chatId, text: message, sender: currUser };
setChatId((prevId) => prevId + 1);
setCurrUser((prevUser) => {
return prevUser === "user" ? "bot" : "user";
});
console.log(`currUser: ${currUser}`);
setMsg((prevMsg) => [...prevMsg, newMsg]);
};
const handleInputChange = (event) => {
setInput(event.target.value);
};
return (
<Box
sx={{
height: "93vh",
display: "flex",
boxSizing: "border-box",
flexDirection: "column",
bgcolor: "grey.200",
margin: "25px 100px",
}}
>
<Box sx={{ flexGrow: 1, overflow: "auto", p: 2 }}>
{msg.map((message, index) => (
<Message key={index} message={message} />
))}
</Box>
<Box sx={{ p: 2, backgroundColor: "background.default" }}>
<Grid container spacing={2}>
<Grid item xs={10}>
<TextField
size="small"
fullWidth
placeholder="Type a message"
variant="outlined"
value={input}
onChange={handleInputChange}
/>
</Grid>
<Grid item xs={2}>
<Button
fullWidth
color="primary"
variant="contained"
endIcon={<SendIcon />}
onClick={handleSend}
>
Send
</Button>
</Grid>
</Grid>
</Box>
</Box>
);
}
const Message = ({ message }) => {
const isBot = message.sender === "bot";
return (
<Box
sx={{
display: "flex",
justifyContent: isBot ? "flex-start" : "flex-end",
mb: 2,
}}
>
<Box
sx={{
display: "flex",
flexDirection: isBot ? "row" : "row-reverse",
alignItems: "center",
}}
>
<Avatar sx={{ bgcolor: isBot ? "primary.main" : "secondary.main" }}>
{isBot ? "B" : "U"}
</Avatar>
<Paper
variant="outlined"
sx={{
p: 2,
ml: isBot ? 1 : 0,
mr: isBot ? 0 : 1,
backgroundColor: isBot ? "primary.light" : "secondary.light",
borderRadius: isBot ? "20px 20px 20px 5px" : "20px 20px 5px 20px",
}}
>
<Typography variant="body1">{message.text}</Typography>
</Paper>
</Box>
</Box>
);
};
export default App;
I tried updating the state variables using the functional way but it still didn’t work.