我有一个使用 RTK createEntityAdapter 从数据库获取数据的用户列表。
获取用户列表的API函数代码
public function index(){
$roles = Role::all();
$all_roles = [];
foreach ($roles as $key => $role) {
$obj_role = new \stdClass();
$obj_role->id = $role->id;
$obj_role->name = $role->title;
array_push($all_roles,$obj_role);
}
return response()->json([
'users' => User::with('roles')->paginate(10),
'roles' => $all_roles
]);
}
在上面的代码中,通过使用 RTK createEntityAdapter 在响应应用程序中获取用户和角色并显示列表
userSlice.js
import { createSlice,createEntityAdapter} from "@reduxjs/toolkit";
import { HTTP_STATUS } from "../../src/constants";
import { fetchUsers, deleteUsers, saveUser } from "services/userService";
const userAdapter = createEntityAdapter({
selectId: (user) => user.id,
})
const userSlice = createSlice({
name:'user',
initialState: userAdapter.getInitialState(
{ loading: false,
page: 1,
total_pages: null,
status: null,
message: null,
roles: []
} ),
reducers:{
pageByNumber: (state,{payload}) => {
state.page = payload.page
},
nextPage: (state, {payload}) => {
state.page = state.page++
},
previousPage: (state, {payload}) => {
state.page = state.page--
},
clear: (state) => {
state.status = null,
state.message = null
}
},
extraReducers: {
[fetchUsers.pending]: (state) => {
state.loading = true,
state.status = HTTP_STATUS.PENDING
},
[fetchUsers.fulfilled]: (state, {payload}) => {
state.loading = false,
state.page = payload.users.current_page,
state.total_pages = Math.ceil(payload.users.total/payload.users.per_page),
userAdapter.setAll(state, payload.users.data),
state.status = HTTP_STATUS.FULFILLED,
state.roles = payload.roles
},
[fetchUsers.rejected]: (state, {error}) => {
state.loading = false,
state.status = HTTP_STATUS.REJECTED,
state.message = error.message
},
[deleteUsers.pending]: (state) => {
state.loading = true,
state.status = HTTP_STATUS.PENDING
},
[deleteUsers.fulfilled]: (state, { payload }) => {
state.loading = false,
userAdapter.removeOne(state, payload.id)
},
[deleteUsers.rejected]: (state) => {
state.loading = false
},
[saveUser.pending]: (state) => {
state.loading = true,
state.status = HTTP_STATUS.PENDING
},
[saveUser.fulfilled]: (state, { payload }) => {
state.loading = false,
state.status = HTTP_STATUS.FULFILLED
if(!payload.errors){
userAdapter.addOne(state, payload.id),
state.message = payload.message
}
},
[saveUser.rejected]: (state,{error}) => {
state.loading = false,
state.status = HTTP_STATUS.REJECTED,
state.message = error.message
}
},
});
export const userSelectors = userAdapter.getSelectors(
(state) => state.user,
)
export const {pageByNumber, nextPage, previousPage,clear} = userSlice.actions
export default userSlice.reducer
用户/index.js
const roles = useSelector(state => state.user.roles);
const allUsers = useSelector(userSelectors.selectAll);
useEffect(() => {
dispatch(
fetchUsers(currentPage))
.then(unwrapResult)
.then((obj) => console.log(obj))
.catch((obj) => console.log({objErr: obj}))
}, [dispatch])
//listing HTML
{
allUsers.map((ls,index) => (
<tr key={ls.id}>
<td>{ls.id}</td>
<td>{ls.name}</td>
<td>{ls.email}</td>
<td>
{ls.status =="ACTIVE" ? <Badge color="success" pill>Active</Badge>:<Badge color="danger" pill>Inactive</Badge>}</td>
<td>
{ls.roles.map((role) => (
role.title+" "
))}
</td>
<td><Moment fromNow ago>{ls.created_at}</Moment> </td>
<td>
<Button variant="warning" size="sm" onClick={handleShow} >Edit</Button>{' '}
<Button
onClick={e =>
window.confirm("Are you sure you wish to delete this user?") &&
deleteUser(ls.id)
}
variant="danger"
size="sm">Delete</Button>
</td>
</tr>
))
}
创建.js
import {Modal, Button, Form,Dropdown} from "react-bootstrap";
import propTypes from "prop-types";
import React, {useState} from "react";
import Multiselect from 'multiselect-react-dropdown';
import { saveUser } from 'services/userService';
import {useDispatch,useSelector} from 'react-redux';
import { unwrapResult } from '@reduxjs/toolkit';
import Notify from "components/Common/Notify";
function Create({handleClose,show,roles}) {
const [selectedRoles, setSelectedRoles] = useState([]);
const dispatch = useDispatch();
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [errors, setErrors] = useState([]);
function onSelectRoles(selectedList, selectedItem) {
selectedRoles.push(selectedItem.id)
}
function onRemoveRole(selectedList, removedItem) {
var index = selectedRoles.indexOf(removedItem.id)
selectedRoles.splice(index, 1);
}
const message = useSelector(state => state.user.message);
const status = useSelector(state => state.user.status);
function onSubmit(e){
e.preventDefault();
let data ={
name:name,
email:email,
password:password,
roles:selectedRoles,
}
dispatch(
saveUser(data))
.then(unwrapResult)
.then((obj) => {
if(obj.errors){
setErrors(obj.errors);
}else{
setErrors([]);
handleClose();
}
}
)
.catch((obj) => {
console.log({objErr: obj})
})
}
return (
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>New User</Modal.Title>
</Modal.Header>
<Modal.Body>
{status && message && (
<Notify status={status} message={message}/>
)}
<Form onSubmit={onSubmit} >
<Form.Group className="mb-3">
<Form.Label>Name</Form.Label>
<Form.Control className={errors['name'] ? "is-invalid" : ""} type="text" onChange={e => setName(e.target.value) } placeholder="Enter Name" />
{errors['name'] ?
<Form.Text className="text-danger">
{errors['name']}
</Form.Text>
:''
}
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control className={errors['email'] ? "is-invalid" : ""} type="email" onChange={e => setEmail(e.target.value) } placeholder="Enter email" />
{errors['email'] ?
<Form.Text className="text-danger">
{errors['email']}
</Form.Text>
:''
}
</Form.Group>
<Form.Group>
<Form.Label>Select Role</Form.Label>
<Multiselect
options={roles}
// selectedValues={selectedValue}
onSelect={onSelectRoles}
onRemove={onRemoveRole}
displayValue="name"
className={errors['roles'] ? "is-invalid" : ""}
/>
{errors['roles'] ?
<Form.Text className="text-danger">
{errors['roles']}
</Form.Text>
:''
}
</Form.Group>
<Form.Group>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control className={errors['password'] ? "is-invalid" : ""} type="password" onChange={e => setPassword(e.target.value)} placeholder="Password" />
{errors['password'] ?
<Form.Text className="text-danger">
{errors['password']}
</Form.Text>
:''
}
</Form.Group>
<Button variant="success" size="sm" type="submit">
Create
</Button>
</Form>
</Modal.Body>
</Modal>
);
}
Create.prototype= {
handleClose: propTypes.func.isRequired,
show: propTypes.bool.isRequired,
roles: propTypes.array.isRequired
}
export default Create;
当我使用 saveUser createEntityAdapter 添加新用户时,没有获取关系数据“角色”并出现错误