1.useEffect

不带依赖 每次都会执行
[] 只执行一次
[userid] userid变化的时候会执行
多个useEffect 依次执行

useEffect(() => {
    if (dispatch) {
      // 获取数据字典数据,项目类型,项目状态
      const types: string[] = ['project_type']
      // eslint-disable-next-line no-restricted-syntax
      for (const key of types) {
        if (!dict[key].length) {
          dispatch({
            type: 'dictionary/fetchDict',
            code: key,
          })
        }
      }
    }
  }, [])

2.useState

setModalVisible异步的 减少dom操作
const [modalVisible, setModalVisible] = useState(false)

3.封装一个Modal 表单

import React, { useState } from 'react'
import { Modal, Form, Input, InputNumber, Select, Row, Col, message } from 'antd'

interface RandomQuestionModalProps {
  visible: boolean
  onClose: () => void
}

// 表单字段类型定义
interface FormValues {
  name: string
  questionCount: number
  difficulty: 'easy' | 'medium' | 'hard' | 'mixed'
  timeLimit: number
  questionType: string[]
  description?: string
}
const RandomQuestionModal: React.FC<RandomQuestionModalProps> = ({ visible, onClose }) => {
  const [form] = Form.useForm()
  const [loading, setLoading] = useState(false)
  // 表单提交
  const handleSubmit = async () => {
    try {
      setLoading(true)
      // 验证并获取表单值
      const values = await form.validateFields()

      // 构造提交数据
      // const projectData = {
      //   name: values.name,
      //   status: 0,
      //   type: 8, // 随机问卷类型
      //   description: values.description || '',
      //   questionCount: values.questionCount,
      //   difficulty: values.difficulty,
      //   timeLimit: values.timeLimit,
      //   questionTypes: values.questionType,
      // }

      // // 调用API创建项目
      // const res = await addProject(projectData, 'add_project')
      // // 成功处理
      // message.success('项目创建成功')
      // form.resetFields() // 重置表单
      onClose() // 关闭弹窗
    } catch (error) {
      message.error('项目创建失败,请重试')
      console.error('创建项目失败:', error)
    } finally {
      setLoading(false)
    }
  }

  const handleCancel = () => {
    onClose()
  }
  return (
    <Modal
      title="随机题目考试设置"
      open={visible}
      onOk={handleSubmit}
      onCancel={handleCancel}
      maskClosable={false}
      confirmLoading={loading}
      destroyOnClose
      width={600}
    >
      <Form
        form={form}
        layout="vertical"
        initialValues={{
          difficulty: 'medium',
          questionCount: 10,
          timeLimit: 30,
        }}
      >
        <Form.Item
          name="name"
          label="项目名称"
          rules={[
            { required: true, message: '请输入项目名称' },
            { max: 50, message: '名称不能超过50个字符' },
          ]}
        >
          <Input placeholder="请输入项目名称" />
        </Form.Item>

        <Row gutter={16}>
          <Col span={12}>
            <Form.Item
              name="questionCount"
              label="题目数量"
              rules={[
                { required: true, message: '请输入题目数量' },
                { type: 'number', min: 5, max: 100, message: '题目数量应在5-100之间' },
              ]}
            >
              <InputNumber min={5} max={100} style={{ width: '100%' }} placeholder="请输入数量" />
            </Form.Item>
          </Col>
          <Col span={12}>
            <Form.Item
              name="timeLimit"
              label="时间限制(分钟)"
              rules={[
                { required: true, message: '请输入时间限制' },
                { type: 'number', min: 5, message: '时间限制不能少于5分钟' },
              ]}
            >
              <InputNumber min={5} style={{ width: '100%' }} placeholder="请输入时间" />
            </Form.Item>
          </Col>
        </Row>

        <Form.Item
          name="difficulty"
          label="难度级别"
          rules={[{ required: true, message: '请选择难度级别' }]}
        >
          <Select placeholder="请选择难度级别">
            <Select.Option value="easy">简单</Select.Option>
            <Select.Option value="medium">中等</Select.Option>
            <Select.Option value="hard">困难</Select.Option>
            <Select.Option value="mixed">混合</Select.Option>
          </Select>
        </Form.Item>

        <Form.Item name="description" label="项目描述">
          <Input.TextArea rows={4} placeholder="请输入项目描述(可选)" />
        </Form.Item>
      </Form>
    </Modal>
  )
}

export default RandomQuestionModal

使用

  const [modalVisible, setModalVisible] = useState(false)
<RandomQuestionModal visible={modalVisible} onClose={() => setModalVisible(false)} />

4.useModel

Umi 框架内置了 useModel Hooks,用于访问通过 src/models 定义的全局模型数据,实现跨组件状态共享。

例如models 中
import { getQuestionTreeList } from '@/services/list'
import { useState, useEffect } from 'react'
import { history } from 'umi'

// export interface IQuestionTypeItem {
// 	createDate: string
// 	createName: string
// 	id: string
// 	orderNum: number
// 	remark?: string
// 	typeCode: string
// 	typeGroupId: string
// 	typeName: string
// 	typeValue?: string
// }
export interface IQuestionTypeItem {
  childList: IQuestionTypeItem[] | null
  code: string
  id: string
  name: string
  parentCode: string
  parentId: string
}

export default function useQuestionTypes() {
  const [questionTypes, setQuestionTypes] = useState<IQuestionTypeItem[]>([])

  useEffect(() => {
    ;(async () => {
      // 如果是公开项目则不请求该接口
      if (history.location.query?.public) {
        return
      }
      // todo ts
      // const ret: IQuestionTypeItem[] = await queryDataDictionary(
      // 	'question_bank_type',
      // )
      // 获取题库列表树
      const ret: IQuestionTypeItem[] = await getQuestionTreeList('question_bank_type')
      setQuestionTypes(ret)
    })()
  }, [])

  return {
    questionTypes,
  }
}

使用

import { useModel } from 'umi'
const { questionTypes } = useModel<any>('useQuestionTypes')

5.循环渲染

<Select 
            placeholder="请选择题目类型" 
            mode="multiple"
            style={{ width: '100%' }}
          >
            {questionTypes.map(type => (
              <Select.Option key={type.value} value={type.value}>
                {type.label}
              </Select.Option>
            ))}
          </Select>

6.条件判断显示隐藏

{isShow ? <div>这是要显示的内容</div> : null}

if语句
if (isShow) {
    content = <div>这是要显示的内容</div>;
  }
  return <div>{content}</div>;

样式
<div 
      style={{ 
        display: isShow ? 'block' : 'none', // 显示/隐藏
        width: 100, 
        height: 100, 
        background: 'red' 
      }}
    >
      内容
    </div>

7.createContext 配合 useContext 多层传递数据

创建 context.ts
import { createContext } from 'react'

export const DictContext = createContext({})

使用 数据dict共用

import { DictContext } from '@/context'
<DictContext.Provider value={dict}>
子组件1
子组件1
子组件1
</DictContext.Provider>

子组件获取

import { DictContext } from '@/context'
import React, { useState, useContext } from 'react'
const dict = useContext(DictContext)

8获取路由参数

import { connect, history, useModel } from 'umi'

history.location.query
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐