刚刚入门react,通过视频学习,做一个简单的react表格功能实现。功能满足对表格数据进行增删改,数据来源于后端接口。交互也与后端接口进行!
话不多说,直接看效果!
接口设置了30%的概率报错,出现错误多刷新几次。
这是后端接口地址 https://public-api-v1.aspirantzhang.com/
浏览器可以直接看到接口数据
项目的搭建是参照于umi官网的快速上手进行搭建的,想要试试的小伙伴可以先将项目搭建起来!https://umijs.org/zh-CN/docs/getting-started
我们的项目主要集中在page下的users文件夹中的内容!
在page下新建uses文件夹
新建这几个文件
我们在components文件夹下放的文件的组件,UserModal,为弹出框组件
import React,{useEffect,FC} from "react"; import {Modal, Button ,Form,Input} from 'antd'; import {SingleUserType,FormValues} from '../data' interface UserModalProps{ visible:boolean; record:SingleUserType|undefined closeHandeler:()=>void onFinish:(values:FormValues)=>void } const UserModal :FC<UserModalProps> = (props)=>{ const[form]=Form.useForm(); const {visible,record,closeHandeler,onFinish} = props // useEffect(参数1,参数2) 当参数2发生改变时,执行参数1 参数1为函数,参数2为数组 useEffect(()=>{ if(record==undefined){ form.resetFields(); } else{ form.setFieldsValue(record); } },[visible]) const onOk=()=>{ form.submit() } const onFinishFailed = () => { console.log('Submit failed!'); }; return( <div> <Modal title="基本信息" visible={visible} onOk={onOk} onCancel={closeHandeler} forceRender> <Form name="basic" form={form} onFinish={onFinish} onFinishFailed={onFinishFailed} > <Form.Item label="姓名" name="name" rules={[ { required: true, message: 'Please input your name!', }, ]} > <Input /> </Form.Item> <Form.Item label="邮箱" name="email"> <Input /> </Form.Item> <Form.Item label="创建时间" name="create_time"> <Input /> </Form.Item> <Form.Item label="状态" name="status"> <Input /> </Form.Item> </Form> </Modal> </div> ) } export default UserModal
在users文件夹下index为主页面,data.a为数据类型,model为模块文件,service为交互后端文件
index.tsx
import React,{ FC, useState} from 'react'; import { Table, Space,Modal, Button,Popconfirm,Tag } from 'antd'; import ProTable, { TableDropdown ,ProColumns, ActionType} from '@ant-design/pro-table'; import { connect,Dispatch, Loading,UserState } from 'umi'; import UserModal from './compoents/UserModal'; import {getRemoteList} from './service' import {SingleUserType,FormValues} from './data.d' interface UserPageProps{ users:UserState, dispatch:Dispatch, userListLoading:boolean, } const UserListPage:FC<UserPageProps> =({users,dispatch,userListLoading})=>{ const [modalVisible,setModalVisible]=useState(false) const [record,setRecord]=useState<SingleUserType|undefined>(undefined) const columns = [ { title: 'ID', dataIndex: 'id', key: 'id', }, { title: '姓名', dataIndex: 'name', key: 'name', render:( text :string) => <a>{text}</a>, }, { title: '邮箱', dataIndex: 'email', key: 'email', render: ( text :string) => <a>{text}</a>, }, { title: '创建时间', dataIndex: 'create_time', key: 'create_time', }, { title: '更新时间', dataIndex: 'update_time', key: 'update_time', }, { title: '状态', dataIndex: 'status', key: 'status', render:tag=>{ let color='#87d068' if(tag!==1){ color = tag == 2 ? '#108ee9' : 'green' } else{ color='#f50' } return <Tag color={color} key={tag}>状态:{tag}</Tag> } }, { title: '操作', key: 'action', render: (text:string,record:SingleUserType) => ( <Space size="middle"> <a onClick={()=>{ editHandler(record) }}>编辑</a> <Popconfirm title="确定要删除这条信息吗?" onConfirm={()=>{ confirm(record) }} okText="Yes" cancelText="No" > <a href="#">删除</a> </Popconfirm> </Space> ), }, ]; const editHandler=(record:SingleUserType)=>{ console.log(record) setModalVisible(true); setRecord(record); } const closeHandeler=()=>{ setModalVisible(false) } // 编辑确认 const onFinish = (values:FormValues) => { let id =0 if(record){ id=record.id; } if(id){ console.log('edit') dispatch({ type:'users/edit', payload:{ id, values } }) } else{ console.log('add') dispatch({ type:'users/add', payload:{ values } }) } setModalVisible(false) }; // 删除确定 const confirm=(record:SingleUserType)=>{ const id=record.id dispatch({ type:'users/delete', payload:{ id } }) } const addHandler=()=>{ setModalVisible(true) setRecord(undefined) } const requestHandler= async ({pageSize,current})=>{ console.log(pageSize,current) const users=await getRemoteList(); return { data:users.data, success:true, total:users.meta.total, } } return( <div className='list-table'> <Button type="primary" onClick={addHandler}>添加</Button> <ProTable columns={columns} dataSource={users.data} rowKey='id' loading={userListLoading} request={requestHandler} search={false} /> <UserModal visible={modalVisible} closeHandeler={closeHandeler} record={record} onFinish={onFinish}></UserModal> </div> ) }; const mapStateToProps = ({users,loading}:{users:UserState,loading:Loading})=>{ console.log(loading) return{ users, userListLoading:loading.models.users, } } export default connect(mapStateToProps)(UserListPage)
data.d.ts
export interface SingleUserType{ "id": number, "name": string, "email": string , "create_time": string , "update_time": string, "status": number } export interface FormValues{ [name:string]:any; }
model.ts
import {Reducer,Effect,Subscription} from 'umi' import users from '.'; import {getRemoteList,editRecord,deleteRecord,addRecord} from './service' import {SingleUserType} from './data.d' export interface UserState{ data:SingleUserType[], meta:{ total:number; per_page:number; page:number; } } interface UserModelType{ namespace:'users'; state:UserState; reducers:{ getList:Reducer<UserState> }; effects:{ getRemote:Effect edit:Effect delete:Effect add:Effect }; subscriptions:{ setup:Subscription; }; } const UserModel: UserModelType = { // 命名空间,也叫标识名 namespace:'users', // 仓库数据初始值 state:{ data:[], meta:{ total:0, per_page:5, page:1, } }, // 同步 //action相当于是{type,payload} type:函数名 payload:数据 reducers:{ getList(state,{payload}){ console.log("reducer here") return payload; } }, // 异步 返回的是一个viod 只能通过reduces返回数据 effects:{ // 异步函数前要加* *getRemote(action,{put,call}){ const data = yield call (getRemoteList) yield put({ type:'getList', payload: data }) }, *edit({payload:{id,values}},{put,call}){ const data = yield call (editRecord,{id,values}) yield put({ type:'getRemote' }) }, *delete({payload:{id}},{put,call}){ const data = yield call (deleteRecord,{id}) yield put({ type:'getRemote' }) }, *add({payload:{values}},{put,call}){ const data = yield call (addRecord,{values}) yield put({ type:'getRemote' }) }, }, // 订阅 subscriptions:{ setup({dispatch,history}){ return history.listen((location,action)=>{ if(location.pathname=='/users'){ console.log("subscription here") dispatch({ type:'getRemote', }); } }); } } }; // 导出model export default UserModel;
service.ts
import { response } from "@umijs/deps/compiled/express"; import { request } from "umi" import { message } from 'antd'; import { FormValues } from "./data"; export const getRemoteList =async () => { return request('/api/users',{ method:'get', }).then(function(response){ console.log("update ok") return response }) .catch(function(error){ console.log(error); }) } export const editRecord =async ({id,values}:{id:number,values:FormValues}) => { return request(`/api/users/${id}`,{ method:'put', data:values }).then(function(response){ message.success('修改成功!'); }) .catch(function(error){ message.error('修改失败!'); }) } export const deleteRecord =async ({id}:{id:number}) => { return request(`/api/users/${id}`,{ method:'delete', }).then(function(response){ message.success('删除成功!'); }) .catch(function(error){ message.error('删除失败!'); }) } export const addRecord =async ({values}:{values:FormValues}) => { return request(`/api/users/`,{ method:'post', data:values }).then(function(response){ message.success('添加成功!'); }) .catch(function(error){ message.error('添加失败!'); }) }
其中路由配置了代理,可以参考我上一篇发布的文章https://www.cnblogs.com/yqPhare/p/16199595.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!