如何仅在JavaScript中映射函数中的某个异步函数之后返回某些内容?
我存储了每封邮件的作者用户id,所以我想获取该用户的用户名。那个么,如何仅在map函数中的数据库调用之后返回列表项呢?我希望我的解释是正确的。代码如下:如何仅在JavaScript中映射函数中的某个异步函数之后返回某些内容?,javascript,reactjs,Javascript,Reactjs,我存储了每封邮件的作者用户id,所以我想获取该用户的用户名。那个么,如何仅在map函数中的数据库调用之后返回列表项呢?我希望我的解释是正确的。代码如下: const messagesRef = firebase.firestore().collection(`/chatrooms/${props.currentChatRoom}/messages`); const query = messagesRef.orderBy('createdAt').limit(25); const [messag
const messagesRef = firebase.firestore().collection(`/chatrooms/${props.currentChatRoom}/messages`);
const query = messagesRef.orderBy('createdAt').limit(25);
const [messages] = useCollectionData(query, { idField: 'id' });
return (
<div className={classes.ChatRoomContainer}>
<ul>
{messages && messages !== null ? messages && messages.map(msg => {
const messageClass = msg.userId === props.userId ? classes.Sent : classes.Recieved;
let messageAuthorUsername;
firebase.firestore().collection('users').doc(msg.author).get().then(doc => {
messageAuthorUsername = doc.data().userName;
return <li className={messageClass + ' ' + classes.Message} key={msg.id}>
<label>{msg.author !== props.userId ? messageAuthorUsername : 'You'}</label>
<p className={classes.MessageContent}>{msg.messageContent}</p>
</li>
});
}) : <p>Loading...</p>}
</ul>
<form className={classes.Form} onSubmit={(e) => props.onMessageSentHandler(e)}>
<input className={classes.Input} placeholder="Type your message..." onChange={(e) => props.onInputChangedHandler(e)} value={props.messageInput} />
<button className={classes.Btn}><FontAwesomeIcon color="white" icon='paper-plane' className={classes.PaperPlaneIcon} /></button>
</form>
</div>
)
您可以将所有
li
项作为数组的一部分保留在名为messageList的状态中。
然后在useffect()
钩子中,您可以从firebase异步获取数据并更新状态
const[messageList,setMessageList]=React.useState([]);
React.useffect(()=>{
messages.map(msg=>{
const messageClass=msg.userId==props.userId?classes.Sent:classes.received;
让messageAuthorName;
firebase.firestore().collection('users').doc(msg.author).get().then(doc=>{
messageAuthorName=doc.data().userName;
}).然后(()=>{
setMessageList(prev=>[…prev,
{msg.author!==props.userId?msg.author:'You'}
{msg.MessageContent}
]
})
}, [])
然后,您可以返回ul
中的消息列表:
{消息和消息!==null?消息&&
消息列表
:正在加载…}
props.onMessageSentHandler(e)}>
props.onInputChangedHandler(e)}值={props.messageInput}/>
您好!当您使用功能组件时,最好的评分方法是使用useEffect挂钩和useState挂钩
从文件中:
什么是钩子?钩子是一个特殊的函数,可以让你“钩住”React特性。例如,useState是一个钩子,可以让你将React状态添加到函数组件中。而且,你可以将useEffect钩子视为componentDidMount、componentDidUpdate和componentWillUnmount的组合
例如:
import React,{useState,useffect}来自“React”;
...
常量应用=()=>{
const[data,setData]=useState();
const[loading,setLoading]=useState();
const[error,setError]=useState();
如果(装载)返回装载。。。;
如果(错误)返回错误!;
useffect(()=>{
设置加载(真);
//您的异步调用
fetchData()
。然后(resData=>{
setData(resData);
设置加载(假);
})
.catch(错误=>{
控制台日志(err);
设置错误(真);
});
}, []);
返回(
{data.map(项=>(
-
))}
);
}
导出默认应用程序;
更多信息
使用状态:useffect:在组件的呈现部分,永远不要将异步函数与
then()
一起使用。理论上,可以在useffect()中使用
,但您将失去firestore的好处。在您的用例中,您应该使用库@react firebase/firestore
和
来正确地执行此操作。Docs:谢谢您的回答,但不幸的是,它没有起作用。因此,只有在执行一些异步函数后才能返回某些内容?但我已经从中获取了数据使用useCollectionData钩子实时访问数据库。我想做的是根据map函数中用户的用户id更改用户名。
const [updatedMessages, setUpdatedMessages] = React.useState([]);
const messagesRef = firebase.firestore().collection(`/chatrooms/${props.currentChatRoom}/messages`);
const query = messagesRef.orderBy('createdAt').limit(25);
const [messages] = useCollectionData(query, { idField: 'id' });
React.useEffect(() => {
if (messages) {
for(let message in messages) {
firebase.firestore().collection('users').doc(messages[message].author).get().then(doc => {
messages[message] = {...messages[message], authorUsername: doc.data().userName};
setUpdatedMessages(prev => [...prev, messages[message]]);
});
}
}
}, [messages]);
return (
<div className={classes.ChatRoomContainer}>
<ul>
{updatedMessages ? updatedMessages.map(msg => {
const messageClass = msg.userId === props.userId ? classes.Sent : classes.Recieved;
return <li className={messageClass + ' ' + classes.Message} key={msg.id}>
<label>{msg.author !== props.userId ? msg.authorUsername : 'You'}</label>
<p className={classes.MessageContent}>{msg.messageContent}</p>
</li>
}) : <p>Loading...</p>}
</ul>
<form className={classes.Form} onSubmit={(e) => props.onMessageSentHandler(e)}>
<input className={classes.Input} placeholder="Type your message..." onChange={(e) => props.onInputChangedHandler(e)} value={props.messageInput} />
<button className={classes.Btn}><FontAwesomeIcon color="white" icon='paper-plane' className={classes.PaperPlaneIcon} /></button>
</form>
</div>
)
{messages ? messages && messages.map(async msg => {
const messageClass = msg.userId === props.userId ? classes.Sent : classes.Recieved;
const messageListItem = await function() {
firebase.firestore().collection('users').doc(msg.author).get().then(doc => {
return <li className={messageClass + ' ' + classes.Message} key={msg.id}>
<label>{msg.author !== props.userId ? doc.data().userName : 'You'}</label>
<p className={classes.MessageContent}>{msg.messageContent}</p>
</li>
});
}
return messageListItem();
}) : <p>Loading...</p>}
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
in ul (at ChatRoom.js:16)
import React, { useState, useEffect } from 'react';
...
const App = () => {
const [data, setData] = useState();
const [loading, setLoading] = useState();
const [error, setError] = useState();
if(loading) return <h2>Loading...</h2>;
if(error) return <h2>Error!</h2>;
useEffect(() => {
setLoading(true);
// your async call
fetchData()
.then(resData => {
setData(resData);
setLoading(false);
})
.catch(err => {
console.log(err);
setError(true);
});
}, []);
return (
<ul>
{data.map(item => (
<li key={item.key}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
);
}
export default App;