首页 > 解决方案 > useQuery 有条件地呈现数据

问题描述

我正在尝试使用我的数据库中useQueryGET数据,然后在我的 REACT 组件中呈现数据,但我不断从我的 JSX 中收到一个长度未定义的错误。谁能看看我的使用useQuery是否不正确?

const SavedBooks = () => {
  const [userData, setUserData] = useState({});
  const { loading, data } = useQuery(GET_ME);
  console.log(loading)
  console.log(data?.me)
  if (loading) {
    return <h2>LOADING...</h2>
  } else {
    setUserData(data?.me);
  }

  // create function that accepts the book's mongo _id value as param and deletes the book from the database
  const handleDeleteBook = async (bookId) => {
    const token = Auth.loggedIn() ? Auth.getToken() : null;

    if (!token) {
      return false;
    }

    try {
      const response = await deleteBook(bookId, token);

      if (!response.ok) {
        throw new Error('something went wrong!');
      }

      const updatedUser = await response.json();
      setUserData(updatedUser);
      // upon success, remove book's id from localStorage
      removeBookId(bookId);
    } catch (err) {
      console.error(err);
    }
  };

  return (
        <>
          <Jumbotron fluid className='text-light bg-dark'>
            <Container>
              <h1>Viewing saved books!</h1>
            </Container>
          </Jumbotron>
            <Container>
              <h2>
                  {userData?.savedBooks.length
                    ? `Viewing ${userData.savedBooks.length} saved ${userData.savedBooks.length === 1 ? 'book' : 'books'}:`
                    : 'You have no saved books!'}
              </h2>
              <CardColumns>
                {userData?.savedBooks.map((book) => {
                  return (
                    <Card key={book.bookId} border='dark'>
                      {book.image ? <Card.Img src={book.image} alt={`The cover for ${book.title}`} variant='top' /> : null}
                      <Card.Body>
                        <Card.Title>{book.title}</Card.Title>
                        <p className='small'>Authors: {book.authors}</p>
                        <Card.Text>{book.description}</Card.Text>
                        <Button className='btn-block btn-danger' onClick={() => handleDeleteBook(book.bookId)}>
                          Delete this Book!
                        </Button>
                      </Card.Body>
                    </Card>
                  )
                })}
              </CardColumns>
            </Container>
        </>
  );
};

数据最终会自己记录在控制台中,但它不会阻止我的 JSX 被渲染,所以我最终 Cannot read property 'length' of undefined在这个区域周围出现了一个:

              <h2>
                  {userData?.savedBooks.length
                    ? `Viewing ${userData.savedBooks.length} saved ${userData.savedBooks.length === 1 ? 'book' : 'books'}:`
                    : 'You have no saved books!'}
              </h2>

标签: reactjsjsxapolloreact-apollo

解决方案


发生错误是因为在某些时候savedBooks=undifiend 所以您需要做的就是检查它是否存在,只需添加另一个?

userData?.savedBooks?.length

<h2>
  {loading ? 'LOADING...' : 
    userData?.savedBooks?.length ? 
    `Viewing ${userData.savedBooks.length} saved ${userData.savedBooks.length === 1 ? 'book' : 'books'}:`
    : 'You have no saved books!'}
</h2>

代码中还有一些东西可能会给你带来问题你不应该直接使用setUserData内部的功能组件主体,这会导致不必要的重新渲染或进入无限渲染循环。

我建议做这样的事情:

useEffect(() => {
  setUserData(data?.me);
}, [data]);

这将使组件仅在data更改时呈现。


推荐阅读