reactjs - 当我尝试在 useEffect 中 setState 时它不起作用

标签 reactjs google-cloud-firestore react-hooks

获取我想要的文档并将其作为对象存储在此处所示的数组中

const appealsRef = collection(db, "appeals");
const today = new Date();
const getAppeals = async (logicalOp) => {
        const q = query(appealsRef, where("toDate", logicalOp, convertDateToTimestamp(today)))
        const querySnapshot = await getDocs(q);
        let dummyAppeals = []; 
        querySnapshot.docs.map((doc) => {
            const docData = { ...doc.data() };
            getOrgByDocID(docData.orgDocID)
                .then((res) => {
                    const appealData = {
                        ...docData,
                        orgName : res.orgName, 
                        orgAddress : res.orgAddress
                    }
                    dummyAppeals.push(appealData)
                    
                })
        });
        return dummyAppeals
    }

我想根据 useEffect 中给出的 ticalOp 在状态变量 currentAppealspastAppeals 中设置结果> 然后使用setAppeals将其设置到另一个状态变量数组appeals中;这是因为根据用户点击的是过去或现在的内容,我想将上诉数组设置为 currentAppeals (如果单击了当前)或 pastAppeals (如果单击了过去)。

涉及的代码:

const [ currentAppeals, setCurrentAppeals ] = useState([]);
const [ appeals, setAppeals ] = useState([]);
useEffect(() => {
        getAppeals(">=")
            .then((res) => {
                setCurrentAppeals(res);
                setAppeals(currentAppeals.map((appeal, i) => {
                    return (
                        <AppealCard
                            appealID={appeal.appealID}
                            from={appeal.fromDate}
                            to={appeal.toDate}
                            orgName={appeal.orgName}
                            orgAddress={appeal.orgAddress}
                            outcome={appeal.outcome}/>
                    )
                }));
            });
    }, []);

然后我将在此处的 react 组件中显示上诉:

<div className='view-appealsBody'>
        {
            appeals
        }
</div>

但是在 useEffect() 中的 setAppeals 之后,未设置上诉

最佳答案

问题

  1. getAppeals 不会等待 dummyAppeals 数组被填充,它只是在 map 回调中的异步代码运行时返回空数组。
  2. React 状态更新是异步处理的,因此当代码尝试将其映射到 JSX 时,currentAppeals 仍然是初始空数组值。
  3. 在 React 中将 JSX 存储在状态中是反模式。您应该在渲染时存储数据并将状态映射到 JSX。这可以避免任何陈旧的外壳超过任何先前的状态值。

解决方案

更新 getAppeals 以返回包含申诉的已解决 promise 数组

const appealsRef = collection(db, "appeals");
const today = new Date();

const getAppeals = async (logicalOp) => {
  const q = query(appealsRef, where("toDate", logicalOp, convertDateToTimestamp(today)));
  const querySnapshot = await getDocs(q);

  return Promise.all(querySnapshot.docs.map((doc) => {
    const docData = { ...doc.data() };
    return getOrgByDocID(docData.orgDocID)
      .then((res) => ({
        ...docData,
        orgName : res.orgName, 
        orgAddress : res.orgAddress
      }))
    })
  );
};

...

const [currentAppeals, setCurrentAppeals] = useState([]);

useEffect(() => {
  getAppeals(">=").then((res) => setCurrentAppeals(res));
}, []);

return (
  ...
  {currentAppeals.map((appeal, i) => (
    <AppealCard
      key={appeal.appealID}
      appealID={appeal.appealID}
      from={appeal.fromDate}
      to={appeal.toDate}
      orgName={appeal.orgName}
      orgAddress={appeal.orgAddress}
      outcome={appeal.outcome}/>
    ))}
  ...
);

关于reactjs - 当我尝试在 useEffect 中 setState 时它不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71404396/

相关文章:

javascript - 如何将转换应用到 material-ui 中的整页并保持 AppBar 固定?

typescript - 使用 Firestore 和 Typescript 的动态 Where 条件

javascript - 异步功能控制台日志记录乱序

reactjs - 使用钩子(Hook) setState 时 throttle 不工作

javascript - 当我使用 React Router ROM 时,组件不会重新渲染

reactjs - 如何在 nextjs 中用两个 url 链接同一个页面

node.js - 尝试发送文件时 FormData 发送空请求

android - Firestore 时间戳为空

reactjs - react : add body class only to certain components in useEffect hook?

javascript - 在 Redux 中没有正确地将 JSON 数据从 reducer 传递到组件