React - 将答案显示为列表

React - display answer as a list

我正在创建一个 React 测验应用程序,但我正在尝试弄清楚如何让我的答案数组显示为列表。到目前为止,这是我的代码

加载数据成功地从 api 加载数据,当我在我的答案变量上进行控制台登录时,我可以看到每个问题的数组都有四个正确的答案。

const loadData = async () => {
  let response = await fetch(
    "https://opentdb.com/api.php?amount=10&category=22&difficulty=medium&type=multiple"
  );
  const data = await response?.json();
  console.log(data);

  const getQuestions = data.results.map((item) => {
    const question = item.question;

     const answers = [...item.incorrect_answers, item.correct_answer];
   
//console.log(answers) shows this as an example 
 ["Quebec", "Ontario", "Nova Scotia", "Alberta"]

    return {
      question: question,
      answers: answers,
    };
  });
  return getQuestions;
};



function App() {
//create useState hook to pass data into
const [showData, setData] = useState([]);

//pass the data into a useeffect hook and setData to the loadData method from above
useEffect(() => {
    (async () => {
      const getData = await loadData();
      setData(getData);
      
    })();
  }, []);


  return (
    <React.Fragment>
      {showData.map((data) => (
        <>
          <div>
            <h1>{data.question}</h1>
          
          <ul>{data.answers}</ul>
         </div>
        </>
      ))}
 
    </React.Fragment>
  );
}

return 函数输出问题,但如果我尝试将答案显示为列表以便我可以单独获取每个答案,它只会将它们放在同一行。

例如: 瑞士的首都是哪个城市?api 苏黎世、法兰克福、维也纳、伯尔尼

任何帮助将不胜感激:)

您可以使用另一个 map:

遍历 answers 数组
<ul>
  {
    data.answers.map((answer) =>
       // It's a good practice to apply a unique identifier as key to your list
       // Not the index, however, as it may change 
       <li key={someValue}>answer</li> 
    ) 
  }
</ul>

您应该迭代答案数组而不是直接渲染它们。 ul 也是无序列表的 parent 标签,你应该使用 li 列出 children.

import { useEffect, useState } from "react";

export default function App() {
  const [showData, setData] = useState([]);
  const loadData = async () => {
    let response = await fetch(
      "https://opentdb.com/api.php?amount=10&category=22&difficulty=medium&type=multiple"
    );
    const data = await response?.json();
    console.log(data);

    const getQuestions = data.results.map((item) => {
      const question = item.question;
      const answers = [...item.incorrect_answers, item.correct_answer];
      return {
        question: question,
        answers: answers
      };
    });
    return getQuestions;
  };

  useEffect(() => {
    (async () => {
      const getData = await loadData();
      setData(getData);
    })();
  }, []);

  return (
    <>
      {showData.map((data,i) => (
        <>
          <div key={i}>
            <h4>{data.question}</h4>
            // map the answers separately
            {data.answers.map((item,j)=><li key={j}>{item}</li>)}
          </div>
        </>
      ))}
    </>
  );
}

在此处检查代码:https://codesandbox.io/s/floral-leftpad-zcwew?file=/src/App.js:0-1063

试试这个 ‍♂️

function App() {
  //create useState hook to pass data into
  const [showData, setData] = useState([]);

  //pass the data into a useeffect hook and setData to the loadData method from above
  useEffect(() => {
    (async () => {
      const getData = await loadData();
      setData(getData);
    })();
  }, []);

  return (
    <React.Fragment>
      {showData.map((data, index) => {
        return (
          <div key={index}>
            <div>
              <h1>{data.question}</h1>
              <ul>
              {data.answers.map((answer, index) => {
                return (
                  <li key={index}>{answer}</li>
                )
              })}
              </ul>
            </div>
          </div>
        );
      })}
    </React.Fragment>
  );
}

export default App;

这里有多个问题:

  1. <ul>{data.answers}</ul> 将不起作用,因为 data.answers 是一个数组。您需要将此数组的元素映射到 <li> 元素,就像您在父元素中所做的那样。
  2. 无论何时使用 map 创建列表,都必须在每个元素上添加一个唯一键,通常是一个 id。我假设问题和答案是唯一的,因此您可以使用数据本身作为键。
  3. 您的代码在访问 response.json() 之前未检查 response.ok。是的,您确实在此处使用了问号运算符,以便特定操作是安全的,但随后下一行的 undefined.results 崩溃了,因此它只会推波助澜并进一步混淆 fetch 错误。
  4. 删除多余的片段<>
  5. 在 es6 中,{questions: questions} 可以是 {questions}.
  6. 当您继续使用该应用程序时,请不要忘记随机排列您的答案。

<script type="text/babel" defer>
const {Fragment, useEffect, useState} = React;

const loadData = async (
  url="https://opentdb.com/api.php?amount=10&category=22&difficulty=medium&type=multiple"
) => {
  const response = await fetch(url);
  
  if (!response.ok) {
    throw Error(response.status);
  }
  
  return (await response.json()).results.map(
    ({question, incorrect_answers, correct_answer}) => ({
      question, 
      answers: [...incorrect_answers, correct_answer]
    })
  );
};

const App = () => {
  const [data, setData] = useState([]);

  useEffect(() => {
    loadData()
      .then(setData)
      .catch(err => console.error(err))
    ;
  }, []);

  return (
    <Fragment>
      {data.map(({question, answers}) => (
        <div key={question}>
          <h3>{question}</h3>
          <ul>
            {answers.map(a => <li key={a}>{a}</li>)}
          </ul>
        </div>
      ))}
    </Fragment>
  );
}

ReactDOM.render(<App />, document.body);

</script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>