未调用 UseEffect

时间:2021-06-22 12:09:50

标签: reactjs asynchronous use-effect

大家好,我有一个关于 useEffect 的问题。我的 useEffect 第一次没有获取数据,我必须切换路由才能获取我需要的数据

const Comments = ({ ...rest }) => {
  const theme = useTheme();
  const classes = useStyles({ theme });
  const [users, setUsers] = useState([]);
  const { push } = useHistory();
  const { token, loading } = useContext(AuthContext)

  const dispatch = useDispatch();
  const allUsers = useSelector(state => state.allUsers);
  const comments = useSelector(state => state.listCommentsByBookId);
  const listBooks = useSelector((state) => state.userListBooks);
  const isFetching = useSelector((state) => state.isFetching);
  const [stateReady, setReadyForRender] = useState(false)

  const redirectTo = ( rowData ) => {
    push({
      pathname: ROUTE.USERS_DETAILS,
      user: rowData
    });
  }

  const options = {
    filterType: 'checkbox',
    selectableRowsHeader: false,
    selectableRowsHideCheckboxes: false,
    selectableRowsOnClick: false,
    onRowClick: redirectTo,
  };

  const getAllComments = async () => {
    var allusersId = [];

    //get all ids
    await allUsers.map((user) => {
      allusersId.push(user.uid);
    })

    //get all books from users 
    await allusersId.map(async (id) => {
      await dispatch(getUserListBooks(apiURL + `api/bdd/userListBooks/${id}`, token))
    })

    var listArray = [];


    //filter the array and delete empty rows
    listArray.push(listBooks);
    var newArray = listArray.filter(e => e);
    
    //map every user and stock the list of books in string 
    await newArray.forEach(async (book)=> {
      await book.map(async (book) => {
        await dispatch(getCommentsByBookId(apiURL + `api/bdd/ratingByBook/${book.id}`, token));
      })
    })
    setReadyForRender(true)  
  }
  
  useEffect(() => {
    console.log('is fetching', isFetching)
    if(comments.length === 0) {
      getAllComments();
    }
  }, [stateReady])

  console.log('COM', comments);

  return (
    <div>
     {stateReady && 
      <Card>
        <Box className={classes.tableContainer} sx={{ minWidth: 1050 }}>
          <MUIDataTable
            data={comments}
            columns={columns}
            options={options}
          />
        </Box>
      </Card>}
    </div>
  );
};

有人知道为什么吗?它可能与异步等待有关,但我被困在这里..谢谢

4 个答案:

答案 0 :(得分:0)

如果您想在第一次渲染时获取这些信息,您必须传递一个空数组作为 useEffect 的第二个参数。

未调用 useEffect 的原因是 stateReady 在当前代码运行过程中不会更改。

参见 this link,特别是 note 部分,它比我更好地解释了空数组作为第二个参数是如何工作的。

答案 1 :(得分:0)

您应该从 stateReady 挂钩中的依赖项数组中删除 useEffect。在依赖项数组中添加变量意味着仅当依赖项之一发生变化时才会触发 use Effect 钩子。以下是如何使用 useEffect 作为生命周期方法 https://reactjs.org/docs/hooks-effect.html

useEffect(() => {
  console.log('is fetching', isFetching)
  if(comments.length === 0) {
    getAllComments();
  }
});

希望这能解决您的问题

答案 2 :(得分:0)

您能否将 useEffect 部分替换为以下代码:

useEffect(() => {
    (async () => {
     console.log('is fetching', isFetching)
    if(comments.length === 0) {
      getAllComments();
    }
    })()
   }, [stateReady])

您可以在此link

中阅读更多相关信息

答案 3 :(得分:0)

当使用钩子编码时,您可以使用 eslint 来显示错误。在这种情况下,如果您希望 useEffect 处理 stateReady,请在函数 getAllComments() => getAllComments(stateReady) 中提供它,并且当您在 useEffect 中以 [stateReady] 作为依赖项调用此函数时,它会起作用。