Skip to content

Commit b80d3ab

Browse files
author
victorsun
committed
upd: react
1 parent a768677 commit b80d3ab

File tree

19 files changed

+12436
-0
lines changed

19 files changed

+12436
-0
lines changed
File renamed without changes.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React from 'react';
2+
import {useDispatch, useSelector} from "react-redux";
3+
import {setName, setAge} from './store/stuSlice';
4+
import {setName as setSchoolName, setAddress as setSchoolAddress} from "./store/schoolSlice";
5+
6+
const App = () => {
7+
// useSelector() 加载state中的数据
8+
// const student = useSelector(state => state.student);
9+
// const school = useSelector(state => state.school);
10+
const {student, school} = useSelector(state => state);
11+
12+
// useDispatch() 获取派发器对象
13+
const dispatch = useDispatch();
14+
15+
const setNameHandler = () => {
16+
dispatch(setName('沙和尚'));
17+
};
18+
const setAgeHandler = () => {
19+
dispatch(setAge(30));
20+
};
21+
22+
return (
23+
<div>
24+
<p>
25+
{student.name} |
26+
{student.age} |
27+
{student.gender} |
28+
{student.address}
29+
</p>
30+
<button onClick={setNameHandler}>修改name</button>
31+
<button onClick={setAgeHandler}>修改age</button>
32+
33+
<hr/>
34+
<p>
35+
{school.name} |
36+
{school.address}
37+
</p>
38+
<button onClick={()=>dispatch(setSchoolName('高老庄中小'))}>修改学校名字</button>
39+
<button onClick={()=>dispatch(setSchoolAddress('高老庄府前街19号'))}>修改学校地址</button>
40+
</div>
41+
);
42+
};
43+
44+
export default App;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import ReactDOM from "react-dom/client";
2+
import App from "./App";
3+
import {Provider} from "react-redux";
4+
import store from './store';
5+
6+
const root = ReactDOM.createRoot(document.getElementById('root'));
7+
root.render(
8+
<Provider store={store}>
9+
<App/>
10+
</Provider>
11+
);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// 使用RTK构建store
2+
import {configureStore} from "@reduxjs/toolkit";
3+
4+
import {stuReducer} from "./stuSlice";
5+
import {schoolReducer} from "./schoolSlice";
6+
7+
const store = configureStore({
8+
reducer:{
9+
student: stuReducer,
10+
school: schoolReducer,
11+
}
12+
});
13+
14+
export default store;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// 创建学校的slice
2+
import {createSlice} from "@reduxjs/toolkit";
3+
4+
const schoolSlice = createSlice({
5+
name: 'school',
6+
initialState:{
7+
name:'花果山一小',
8+
address:'花果山大街28号'
9+
},
10+
reducers:{
11+
setName(state, action){
12+
state.name = action.payload;
13+
},
14+
setAddress(state, action){
15+
state.address = action.payload;
16+
}
17+
}
18+
});
19+
20+
export const {setName, setAddress} = schoolSlice.actions;
21+
export const {reducer:schoolReducer} = schoolSlice;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {createSlice} from "@reduxjs/toolkit";
2+
3+
// createSlice 创建 reducer 切片
4+
const stuSlice = createSlice({
5+
name:'stu', // 对应 action 中的 type
6+
initialState:{ // state的初始值
7+
name:'孙悟空',
8+
age:18,
9+
gender:'男',
10+
address:'花果山'
11+
},
12+
reducers:{ // 指定state的操作
13+
setName(state, action){
14+
state.name = action.payload;
15+
},
16+
setAge(state, action){
17+
state.age = action.payload;
18+
}
19+
}
20+
});
21+
22+
// actions中存储切片自动生成action创建器(函数),调用函数后会自动创建action对象
23+
// action对象的结构 {type:name/函数名, payload:函数的参数}
24+
export const {setName, setAge} = stuSlice.actions;
25+
export const {reducer:stuReducer} = stuSlice;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from 'react';
2+
import {useDelStudentMutation, useGetStudentsQuery} from "./store/studentApi";
3+
import StudentList from "./components/StudentList";
4+
5+
const App = () => {
6+
7+
const result = useGetStudentsQuery(null, {
8+
// useQuery 可以接收一个对象作为第二个参数,通过该对象可以对请求进行配置
9+
// selectFromResult: result => {
10+
// if (result.data) {
11+
// result.data = result.data.filter(item => item.attributes.age < 18);
12+
// }
13+
// return result;
14+
// }, // 用来指定useQuery返回的结果
15+
16+
pollingInterval:0, // 设置轮询的间隔,单位毫秒 如果为0则表示不轮询
17+
skip:false, // 设置是否跳过当前请求,默认false
18+
refetchOnMountOrArgChange:false, // 设置是否每次都重新加载数据 false正常使用缓存,
19+
// true每次都重载数据
20+
// 数字,数据缓存的时间(秒)
21+
refetchOnFocus:false, // 是否在重新获取焦点时重载数据
22+
refetchOnReconnect:true, // 是否在重新连接后重载数据
23+
});
24+
25+
/*
26+
currentData: undefined // 当前参数的最新数据
27+
data: undefined // 最新的数据
28+
isError: false // 布尔值,是否有错误
29+
error: Error() // 对象,有错时才存在
30+
isFetching: true // 布尔值,数据是否在加载
31+
isLoading: true // 布尔值,数据是否第一次加载
32+
isSuccess: false // 布尔值,请求是否成功
33+
isUninitialized: false // 布尔值,请求是否还没有开始发送
34+
refetch: ƒ () // 一个函数,用来重新加载数据
35+
status: "pending" // 字符串,请求的状态
36+
*/
37+
38+
const {data: stus, isSuccess, isLoading, refetch} = result; // 调用Api中的钩子查询数据
39+
40+
return (
41+
<div>
42+
<button onClick={() => refetch()}>刷新</button>
43+
{isLoading && <p>数据加载中...</p>}
44+
{isSuccess && <StudentList stus={stus}/>}
45+
</div>
46+
);
47+
};
48+
49+
export default App;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React, {useCallback, useContext, useState} from 'react';
2+
import StudentForm from "./StudentForm";
3+
import {useDelStudentMutation} from "../store/studentApi";
4+
5+
const Student = (props) => {
6+
7+
const [isEdit, setIsEdit] = useState(false);
8+
// 获取删除的钩子,useMutation的钩子返回的是一个数组
9+
// 数组中有两个东西,第一个是操作的触发器,第二个是结果集
10+
const [delStudent, {isSuccess}] = useDelStudentMutation();
11+
12+
13+
const deleteHandler = () => {
14+
delStudent(props.stu.id);
15+
};
16+
17+
const cancelEdit = () => {
18+
setIsEdit(false);
19+
};
20+
21+
return (
22+
<>
23+
{(!isEdit && !isSuccess) &&
24+
<tr>
25+
<td>{props.stu.attributes.name}</td>
26+
<td>{props.stu.attributes.gender}</td>
27+
<td>{props.stu.attributes.age}</td>
28+
<td>{props.stu.attributes.address}</td>
29+
<td>
30+
<button onClick={deleteHandler}>删除</button>
31+
<button onClick={() => setIsEdit(true)}>修改</button>
32+
</td>
33+
</tr>
34+
}
35+
36+
{
37+
isSuccess && <tr>
38+
<td colSpan="5">
39+
数据已删除!
40+
</td>
41+
</tr>
42+
}
43+
44+
{isEdit && <StudentForm stuId={props.stu.id} onCancel={cancelEdit}/>}
45+
46+
{/*{loading && <tr>*/}
47+
{/* <td colSpan={5}>正在删除数据...</td>*/}
48+
{/*</tr>}*/}
49+
{/*{error && <tr>*/}
50+
{/* <td colSpan={5}>删除失败...</td>*/}
51+
{/*</tr>}*/}
52+
</>
53+
54+
);
55+
};
56+
57+
export default Student;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.student-form input{
2+
width: 80px;
3+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import React, {useCallback, useContext, useEffect, useState} from 'react';
2+
import './StudentForm.css';
3+
import {useAddStudentMutation, useGetStudentByIdQuery, useUpdateStudentMutation} from "../store/studentApi";
4+
5+
const StudentForm = (props) => {
6+
// 调用钩子来加载数据
7+
const {data:stuData, isSuccess, isFetching} = useGetStudentByIdQuery(props.stuId, {
8+
skip:!props.stuId,
9+
refetchOnMountOrArgChange:false
10+
});
11+
// 用户修改时,表单中的数据是数据库中最新的数据
12+
const [inputData, setInputData] = useState({
13+
name: '',
14+
age: '',
15+
gender: '男',
16+
address: ''
17+
});
18+
19+
const [addStudent, {isSuccess:isAddSuccess}] = useAddStudentMutation();
20+
const [updateStudent, {isSuccess:isUpdateSuccess}] = useUpdateStudentMutation();
21+
22+
// StudentForm一加载,应该去自动的加载最新的学生数据
23+
// console.log(props.stuId);
24+
// console.log(isSuccess, stuData);
25+
26+
useEffect(()=>{
27+
if(isSuccess){
28+
setInputData(stuData.attributes);
29+
}
30+
}, [isSuccess])
31+
32+
const nameChangeHandler = (e) => {
33+
setInputData(prevState => ({...prevState, name: e.target.value}));
34+
};
35+
36+
const ageChangeHandler = (e) => {
37+
setInputData(prevState => ({...prevState, age: +e.target.value}));
38+
};
39+
40+
const genderChangeHandler = (e) => {
41+
setInputData(prevState => ({...prevState, gender: e.target.value}));
42+
};
43+
44+
const addressChangeHandler = (e) => {
45+
setInputData(prevState => ({...prevState, address: e.target.value}));
46+
};
47+
48+
const submitHandler = () => {
49+
addStudent(inputData);
50+
// 重置数据
51+
setInputData({
52+
name: '',
53+
age: '',
54+
gender: '男',
55+
address: ''
56+
});
57+
};
58+
59+
const updateHandler = () => {
60+
updateStudent({
61+
id:props.stuId,
62+
attributes:inputData
63+
});
64+
props.onCancel();
65+
};
66+
67+
68+
return (
69+
<>
70+
<tr className="student-form">
71+
<td><input
72+
onChange={nameChangeHandler}
73+
value={inputData.name}
74+
type="text"/></td>
75+
<td>
76+
<select
77+
onChange={genderChangeHandler}
78+
value={inputData.gender}
79+
>
80+
<option value="男"></option>
81+
<option value="女"></option>
82+
</select>
83+
</td>
84+
<td><input
85+
onChange={ageChangeHandler}
86+
value={inputData.age}
87+
type="text"/></td>
88+
<td><input
89+
onChange={addressChangeHandler}
90+
value={inputData.address}
91+
type="text"/></td>
92+
<td>
93+
94+
{props.stuId && <>
95+
<button onClick={()=>props.onCancel()}>取消</button>
96+
<button onClick={updateHandler}>确认</button>
97+
</>}
98+
{!props.stuId &&
99+
<button
100+
onClick={submitHandler}
101+
>添加
102+
</button>
103+
}
104+
105+
</td>
106+
</tr>
107+
{/*{loading && <tr>*/}
108+
{/* <td colSpan={5}>添加中...</td>*/}
109+
{/*</tr>}*/}
110+
{/*{error && <tr>*/}
111+
{/* <td colSpan={5}>添加失败</td>*/}
112+
{/*</tr>}*/}
113+
</>
114+
115+
);
116+
};
117+
118+
export default StudentForm;

0 commit comments

Comments
 (0)