所以我有一张使用 map 方法填充的销售人员表。该表中的每一行都有一个“编辑”按钮,应该 1) 获取行的 id,2) 使用反应查询从数据库中获取该记录的数据,以及 3) 打开一个模式并将对象数据传递给填充输入字段的模式。
此时,我可以通过使用 react 查询响应直接将数据传递给模态来完成上述操作,但是我想将该响应放入一个useState
变量中以在本地跟踪我的状态以进行客户端操作(例如,当添加新的销售人员时,我需要将一个空对象传递给模态而不是最后一个查询结果)。
我很确定会这样做,我需要以useEffect
某种方式合并,但我无法让它正常工作。会认为这就像在 useeffect 函数中更新 usestate 变量一样简单,如下所示:
我试着做这样的事情:
const [salespersonToModify, setSalespersonToModify] = React.useState({})
.....
React.useEffect(() => {
console.log(`effect salesperson:${idToEdit}`)
setSalespersonToModify(fetchedSalesperson)
}, [fetchedSalesperson])
.....
<ModifySalespersons
isOpen={isOpen}
setIsOpen={setIsOpen}
salesperson={salespersonToModify}
onSubmit={handleSubmit}
/>
但我没有任何运气。希望有人可以提供帮助。完整代码如下
import React, { useState, useEffect, useRef } from 'react';
import { useQuery, useMutation, useQueryCache, QueryCache, ReactQueryCacheProvider } from 'react-query'
import ModifySalespersons from '../components/ModifySalespersons'
function Salespersons(props){
const [page, setPage] = React.useState(1)
const [hasNextPage, setHasNextPage] = React.useState(true)
const [hasPreviousPage, setHasPreviousPage] = React.useState(false)
const [isOpen, setIsOpen] = React.useState(false)
const [idToEdit, setIdToEdit] = React.useState(0)
// api calls to abstract out
const fetchSalespersons = async (key, { page = 1 }) => {
const res = await fetch(`http://localhost:5000/api/salespersons?pagenumber=${page}&pagesize=4`);
let pagination = JSON.parse(res.headers.get("X-Pagination"));
setHasNextPage(pagination.hasNext);
setHasPreviousPage(pagination.hasPrevious);
return res.json();
}
const fetchSalesperson = async (key, salespersonId) => {
const res = await fetch(`http://localhost:5000/api/salespersons/${salespersonId}`);
return res.json();
}
const { data: salespersons, status: salespersonsStatus } = useQuery(['salespersons', { page } ], fetchSalespersons)
const { data: fetchedSalesperson, status: fetchedSalespersonStatus } = useQuery(['foundSalesperson', idToEdit], fetchSalesperson)
function addSalesPerson(){
// setFetchedSalesperson({});
setIsOpen(true);
}
function editSalesPerson(salespersonId){
fetchSalesperson(salespersonId)
.then((salesperson) => {
setIdToEdit(salespersonId)
setIsOpen(true);
});
}
React.useEffect(() => {
console.log(`effect salesperson:${idToEdit}`)
}, [idToEdit])
function handleSubmit(newSalesperson) {
console.log(newSalesperson);
// call api to create or update record
setIsOpen(false);
}
return (
<>
{fetchedSalespersonStatus === 'success' && (
<ModifySalespersons
isOpen={isOpen}
setIsOpen={setIsOpen}
salesperson={fetchedSalesperson}
onSubmit={handleSubmit}
/>
)}
{salespersonsStatus === 'loading' && (
<div class="fixed inset-0 transition-opacity flex items-center justify-center">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
<button type="button" class="z-50 inline-flex items-center px-12 py-8 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition ease-in-out duration-150 cursor-not-allowed" disabled="">
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<p className="text-xl">
Loading
</p>
</button>
</div>
)}
{salespersonsStatus === 'error' && (
<div>
Error
</div>
)}
{salespersonsStatus === 'success' && (
<div onKeyDown={(event) => {if(event.key === "Escape") setIsOpen(false)}} tabIndex="0">
<div className="pb-5 border-b border-gray-200 space-y-3 sm:flex sm:items-center sm:justify-between sm:space-x-4 sm:space-y-0">
<h2 className="text-lg leading-6 font-medium text-gray-900">
Salespeople
</h2>
<div>
<span className="shadow-sm rounded-md">
<button onClick={ () => addSalesPerson() } type="button" className="inline-flex items-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline-indigo focus:border-indigo-700 active:bg-indigo-700 transition duration-150 ease-in-out">
Add new salesperson
</button>
</span>
</div>
</div>
<div className="flex flex-col">
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
<div className="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
<table className="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th className="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
Id
</th>
<th className="px-6 py-3 bg-gray-50"></th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{ salespersons.map((salesperson, index) => (
<tr>
<td className="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
{salesperson.salespersonId}
</td>
<td className="px-6 py-4 whitespace-no-wrap text-right text-sm leading-5 font-medium">
<button onClick={ () => editSalesPerson(salesperson.salespersonId) } className="text-indigo-600 hover:text-indigo-900">Edit</button>
</td>
</tr>
))}
</tbody>
</table>
<nav className="bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6">
<div className="flex-1 flex justify-between sm:justify-end">
<PageButtons page={page} setPage={setPage} hasPreviousPage={hasPreviousPage} hasNextPage={hasNextPage}></PageButtons>
</div>
</nav>
</div>
</div>
</div>
</div>
</div>
)}
</>
);
}
function PageButtons(props) {
return (
<>
{ props.hasPreviousPage && (
<button onClick={ () => props.setPage(props.page - 1) } className="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-gray-700 bg-white hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
Previous
</button>
)}
{ props.hasNextPage && (
<button onClick={ () => props.setPage(props.page + 1) } className="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-gray-700 bg-white hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
Next
</button>
)}
</>
);
}
export default Salespersons;