如何仅在JavaScript中映射函数中的某个异步函数之后返回某些内容?

如何仅在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

我存储了每封邮件的作者用户id,所以我想获取该用户的用户名。那个么,如何仅在map函数中的数据库调用之后返回列表项呢?我希望我的解释是正确的。代码如下:

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;