React 每日一练

React-Exercise-day-02

App.tsx

import { Question } from './Question'
import { QuestionData } from './QuestionData'
import './styles.css'

function App() {
  return (
    <>
      <h1>FAQ</h1>
      <div className="container">
        <h2>Frequently Asked Questions</h2>
        <div className="questions">
          {questionsList.map((question) => (
            <Question key={question.id} question={question}></Question>
          ))}
        </div>
      </div>
    </>
  )
}
export default App
const questionsList: QuestionData[] = [
  {
    id: 1,
    title: 'hello',
    info: 'hello',
  },
  {
    id: 2,
    title: 'hi',
    info: 'hi',
  },
  {
    id: 3,
    title: 'hah',
    info: 'hah',
  },
]

Question.tsx

import { useState } from 'react'
import { QuestionData } from './QuestionData'

// 最好写在Quesiton.tsx文件下,因为这是react组件的参数类型
type QuestionProps = {
  question: QuestionData
}

enum SwichState {
  OPEN = 'open',
  CLOSED = 'closed',
}

export function Question({ question }: QuestionProps) {
  const [isOpen, setOpen] = useState<boolean>(false)
  return (
    <section>
      <div className={isOpen ? SwichState.OPEN : SwichState.CLOSED}>
        <h4>{question.title}</h4>
        <button onClick={() => setOpen(!isOpen)}>{isOpen ? 'close' : 'open'}</button>
      </div>
      {isOpen && <p>{question.info}</p>}
    </section>
  )
}

QuestionData.ts

export type QuestionData = {
  id: number
  title: string
  info: string
}

styles.css

html {
  font-family: Arial, Helvetica, sans-serif;
}

.container {
  background-color: rgb(10, 27, 184);
  max-width: 600px;
  padding: 10px 20px 20px;
  border-radius: 12px;
  margin: 0 auto;
}

h1 {
  text-align: center;
}

.container h2 {
  margin: 0 auto;
  text-align: center;
  padding: 10px 0 20px 0;
  color: white;
}

button {
  background: rgb(211, 216, 253);
  color: rgb(10, 27, 184);
  border: 2px solid rgb(10, 27, 184);
  border-radius: 5px;
  font-size: 20px;
}

section div,
section p {
  background-color: white;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
  margin-top: 0px;
}

section p {
  padding-bottom: 20px;
}

section > div.closed {
  margin-bottom: 20px;
}

在父组件App中,首先使用了import语句导入了Question组件和QuestionData类型,并且导入了样式文件styles.css。然后,使用了questionsList数组存储了一些问题的数据,其中每个问题都包括一个id、一个title和一个info

App组件中,首先渲染了一个标题和一个包含问题的容器。在问题容器中,使用了questionsList.map()方法遍历了所有问题数据,并将每个问题的idtitleinfo作为属性传递给Question组件,渲染出所有问题。

子组件Question定义了一个接口类型QuestionProps,用于指定传入该组件的参数类型。接着使用了一个枚举类型SwitchState表示问题的状态,包括openclosed两种状态。

Question组件中,首先使用了useState钩子函数创建了一个isOpen状态,并将初始值设置为false。然后根据问题的状态渲染了一个包含标题和按钮的div元素,其中按钮的文字根据问题的状态进行切换。当按钮被点击时,使用了setOpen函数改变了问题的状态,并在问题打开时渲染了一个包含问题描述信息的p元素。

效果图:

image-20230311094550963