为什么我不能在 React State 上使用点符号?

Why can't I use dot notation on React State?

我正在创建一个抽认卡应用程序,我目前正在尝试将抽认卡的正面设置为 API 中的一些文本。

我的状态:

const [deckWithCards, setDeckWithCards] = useState([]);

deckWithCards 是一副抽认卡,看起来像:

{name: 'Test Name', description: 'Test Description', id: 3, cards: Array(4)};

当我 deckWithCards.cards 我得到:

[{id: 1, front: 'Front of card', back: 'Back of Card', deckId: 1}]

如果我在一副牌中有 4 张牌,我将得到一个包含 4 个对象和相应数据的数组。

我需要访问所有这些信息,但是,当我尝试执行 deckWithCards.cards.front 时,我得到“无法读取未定义的 属性 'front'”。

我也试过像这样遍历卡片数组:

let arr = [];
let allCards = deckWithCards.cards;
for (let i = 0; i < allCards.length; i++) {
   arr.push(allCards.front);
}

这给了我:“无法读取未定义的 属性 'length'。”

如何访问此卡片数组中的项目?

辅助函数:

export async function readDeck(deckId, signal) {
  const url = `${API_BASE_URL}/decks/${deckId}?_embed=cards`;
  return await fetchJson(url, { signal });
}

export async function listCards(deckId, signal) {
  const url = `${API_BASE_URL}/cards?deckId=${deckId}`;
  return await fetchJson(url, { signal });
}

我如何设置状态:

useEffect(() => {
    const abortController = new AbortController();

      readDeck(deckId, abortController.signal)
      .then(setDeckWithCards)
      .catch(setError)

      listCards(deckId, abortController.signal)
        .then(setCards)
        .catch(error)

      return () => abortController.abort();
  }, []);

首先第一个状态是[]

const [deckWithCards, setDeckWithCards] = useState([]);

所以在第一个 运行 中,我除了 deckWithCards 是一个没有 属性 cards 的数组。这可能会触发您遇到的错误。

否则,如果 deckWithCards 是一个对象数组,那么要访问第一个对象的卡片,您需要输入 deckWithCards[0].cards

相反,如果您使用上述对象正确设置 deckWithCards 的值,则 deckWithCards.cards 应该正确地 return 卡片的例外列表。

有一段时间你的 useEffect 和你的 fetch 在你设置卡片之前仍然 运行ning。在此期间,deckWithCards 的值将成为您在 useState 中提供的初始值。您的组件必须以能够正确 运行 并使用该初始值正确呈现的方式构建。如果已解析牌组的最终值是 object,那么您的初始值是一个空数组是没有意义的。

const [deckWithCards, setDeckWithCards] = useState([]);

我建议您将初始状态设置为nullundefined。在访问 deckWithCards 上的任何属性之前,您必须检查它是否已设置为实际值。

const [deckWithCards, setDeckWithCards] = useState(null);
const allCards = deckWithCards ? deckWithCards.cards : [];

这里我们检查 deckWithCards 是否是 truthy(不是 null)。如果我们有一个牌组,那么我们就可以从牌组中访问卡片。如果还是null,我们就用一个空数组。无论哪种方式,allCards 将始终是一个 array,您可以 map、循环等

const fronts = allCards.map( card => card.front );
return (
  <ul>
    {allCards.map( (card) => (
       <div className="card" key={card.id}>
          {card.front}
       </div>
    ))}
  </ul>
)