为什么会发生这种情况?:TypeError:无法读取 REACT 中未定义的属性“用户名”
我正在尝试在 React 中创建一个 Messenger 克隆应用程序,但我真的不知道发生了什么事情导致了这个错误:
TypeError: Cannot read property 'username' of undefined
为什么突然出现这个错误?
请看一下!
所以我有两个文件,第一个是 App.js :
import React, { useState, useEffect } from "react";
import { Button, InputLabel, Input, FormControl } from "@material-ui/core";
import "./App.css";
import Message from "./Message";
import db from "./firebase";
import firebase from "firebase";
import FlipMove from "react-flip-move";
function App() {
const [input, setInput] = useState("");
const [messages, setMessages] = useState([{}]);
const [username, setUsername] = useState("");
useEffect(() => {
db.collection("messages")
.orderBy("timestamp", "desc")
.onSnapshot((snapshot) => {
setMessages(
snapshot.docs.map((doc) => ({ id: doc.data, message: doc.data() }))
);
});
}, []);
useEffect(() => {
setUsername(prompt("please enter your name"));
}, []);
const sendMessage = (event) => {
event.preventDefault();
db.collection("messages").add({
message: input,
username: username,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
});
setInput("");
};
return (
<div className="App">
<h1>Hello</h1>
<h2>welcome {username}</h2>
<form className="send">
<FormControl>
<InputLabel>Enter a message..</InputLabel>
<Input
value={input}
onChange={(event) => setInput(event.target.value)}
/>
<Button
disabled={!input}
variant="contained"
color="primary"
type="submit"
onClick={sendMessage}
>
Send Message
</Button>
</FormControl>
</form>
<FlipMove>
{messages.map(({ id, message }) => (
<Message key={id} username={username} message={message} />
))}
</FlipMove>
</div>
);
}
export default App;
第二个是 Message.js ,错误发生在其中:
import { Card, CardContent, Typography } from "@material-ui/core";
import React, { forwardRef } from "react";
import "./Message.css";
const Message = forwardRef(({ message, username }, ref) => {
const isUser = username === message.username;
return (
<div ref={ref} className={`message ${isUser && "message_user"}`}>
<Card className={isUser ? "message_userCard" : "message_guestCard"}>
<CardContent>
<Typography color="white" variant="h5" component="h2">
{message.username}: {message.message}
</Typography>
</CardContent>
</Card>
</div>
);
});
export default Message;
错误在这行
const isUser = username === message.username;
这意味着作为 prop 传递给
Message
组件的
message
值是未定义的。
因此,当您在此处迭代消息时,
messages
数组中至少有一个对象的
message
键没有定义值:
<FlipMove>
{messages.map(({ id, message }) => (
<Message key={id} username={username} message={message} />
))}
</FlipMove>
尝试在
render()
函数之前打印出整个
messages
数组并检查存在哪些值。
尝试更改此行:
const [messages, setMessages] = useState([{}]);
更改为:
const [messages, setMessages] = useState([]);
编辑:问题在于以下这一行意味着您正在将
messages
数组初始化为:
[{}]
:
const [messages, setMessages] = useState([{}]);
这意味着您的数组中有一个元素,即一个空对象 {}。 它会一直保持这种状态,直到您的数据库读取完成并用您的真实数据填充您的数组。所以第一次,您的渲染函数将尝试理解这个只有这一个空对象的数组。
因此,当您像这样迭代它时:
{messages.map(({ id, message }) => (
<Message key={id} username={username} message={message} />
))}
然后对于每个元素,由于这个解构赋值(如果您不确定那是什么,请查找该术语),它将查找
id
和
message
属性:
({ id, message })
因此,由于您从数组中的一个空对象元素开始,它将查找该空对象的
.message
属性,但该属性不存在。它将是
undefined
。此
undefined
将作为 prop 传递给您的
Message
组件。然后在您的
Message
组件中,此行:
const isUser = username === message.username;
尝试访问
undefined
上的
.username
属性,因为请记住,
message = undefined
,因为这是您无意中作为 prop 传递的。这就是为什么错误抱怨它在
undefined
上找不到
username
属性的原因:
TypeError: Cannot read property 'username' of undefined