React-bootstrap table axios 调用后未刷新
React-bootstrap table not refreshed after axios call
我有一个 table 可以在页面加载时完美运行,该页面还包含一个模态组件来更新 table 的一行,我正在使用自定义挂钩来制作 API 调用并且效果很好。
问题是修改了一行后,没找到刷新table的方法。 DB 得到更新,Toast 显示更新成功,对新列表的调用被触发并在 DBHook 中使用 console.log('Result', result) 获得新列表但是,具有加热依赖性的 useEffect 从不被解雇。
如果我转到另一个页面然后返回或按 F5,列表会正确刷新。
dbHook :
export const useAxios = (url, method, data) => {
const [responseData, setResponseData] = useState(undefined)
const [status, setStatus] = useState(undefined)
const [error, setError] = useState('')
const [loading, setLoading] = useState(true)
const params = {
method: method,
url: url,
headers: { accept: '*/*' },
data: data,
}
const fetchData = async (params) => {
//console.log('in axios', method, url, data)
try {
const result = await axios.request(params)
//console.log('Result', result)
setResponseData(result.data)
setStatus(result.status)
//console.log('resultStatus', result.status)
} catch (error) {
setError(error.response)
//console.log('Error', error)
} finally {
setLoading(false)
//console.log('axios finished', url)
}
}
useEffect(() => {
fetchData(params)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url])
return { responseData, error, loading, status }
}
模态:
export default function HeatModal({
isShow,
triggerModal,
activeHeat,
setActiveHeat,
saveHeat,
}) {
function save() {
saveHeat()
triggerModal()
}
return (
<>
<Modal show={isShow} onHide={triggerModal}>
<Modal.Header>
<Modal.Title>{activeHeat.name}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<FormGroup as={Row}>
<FormLabel column>
Nouvelle date de chaleur
</FormLabel>
<Col>
<MyDatePicker
field={'date'}
value={activeHeat.date}
setter={setActiveHeat}
/>
</Col>
</FormGroup>
</Form>
</Modal.Body>
<Modal.Footer as={NavContainer}>
<Button variant="outline-success" onClick={triggerModal}>
Annuler
</Button>
<Button variant="success" onClick={save}>
Confirmer
</Button>
</Modal.Footer>
</Modal>
</>
)
}
列表:
const HeatList = () => {
const [heatsUrl, setHeatsUrl] = useState('/heats')
const heat = {
idHeat: -1,
name: '',
date: new Date(),
idDog: -1,
}
const [heatsWithName, setHeatsWithNames] = useState([])
const [heatPerPage, setHeatPerPage] = useState(10)
const [firstHeat, setFirstHeat] = useState(0)
const [showModal, setShowModal] = useState(false)
const [activeHeat, setActiveHeat] = useState(heat)
const [editUrl, setEditUrl] = useState('')
const {
responseData: heats,
loading: heatsIsLoading,
error: heatsIsError,
} = useAxios(heatsUrl, 'GET', null)
const { responseData: dogs, loading: dogsIsLoading } = useAxios(
'/dogs',
'GET',
null
)
const { responseData: editResponse, loading: editLoading } = useAxios(
editUrl,
'PUT',
activeHeat
)
useEffect(() => {
console.log('activeHeat', activeHeat.idHeat)
editResponse && console.log('editResponse', editResponse.idHeat)
if (editResponse && activeHeat.idHeat === editResponse.idHeat) {
console.log('in use Effect2')
setActiveHeat(editResponse)
toastSuccess(SAVE_SUCCESS)
setHeatsUrl('/heats')
} else if (editResponse === '') {
console.log('in use Effect3')
toastError(SAVE_ERROR)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [editResponse])
useEffect(() => {
console.log('in new heats array')
let newHeatsArr = []
if (heats && dogs) {
console.log('in if', heats)
heats.map((h) => newHeatsArr.push(buildHeat(h, true)))
}
setHeatsWithNames(newHeatsArr)
console.log('newHeatsArray', newHeatsArr)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [heats, dogs])
const { items, requestSort, sortConfig } = useSortableData(heatsWithName)
const getClassNamesFor = (name) => {
if (!sortConfig) {
return
}
return sortConfig.key === name ? sortConfig.direction : undefined
}
const triggerModal = () => {
setShowModal((prev) => !prev)
}
function buildHeat(origHeat, withName) {
const newHeat = {
idHeat: origHeat.idHeat,
date: origHeat.date,
idDog: origHeat.idDog,
}
if (withName) {
let dogName =
dogs && dogs.find((d) => d.idDog === origHeat.idDog).name
Object.assign(newHeat, dogName && { name: dogName })
}
return newHeat
}
const modifyHeat = (h) => {
setActiveHeat(h)
triggerModal()
}
const saveHeat = () => {
console.log('aH', activeHeat)
setEditUrl('/heat/' + activeHeat.idHeat)
}
return (
<Container>
{heatsIsLoading || dogsIsLoading ? (
<Spinner animation="border" variant="primary" />
) : (
<div className="table-container">
<h1 className="text-center">Liste des chaleurs</h1>
<HeatModal
isShow={showModal}
triggerModal={triggerModal}
activeHeat={activeHeat}
setActiveHeat={setActiveHeat}
saveHeat={saveHeat}
/>
<Paginator
items={items}
dogPerPage={heatPerPage}
setDogPerPage={setHeatPerPage}
firstDog={firstHeat}
setFirstDog={setFirstHeat}
/>
<Table
striped
bordered
hover
responsive
className="table-fixed"
>
<thead>
<tr>
<th>
<button
type="buttton"
onClick={() => requestSort('name')}
className={getClassNamesFor('name')}
>
Nom
</button>
</th>
<th>
<button
type="buttton"
onClick={() => requestSort('date')}
className={getClassNamesFor('date')}
>
Date dernière chaleur
</button>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{items &&
items
.slice(
firstHeat,
Number(firstHeat) + Number(heatPerPage)
)
.map((heat) => (
<tr key={heat.idHeat}>
<td>{heat.name}</td>
<td>
{formatDate().format(
new Date(heat.date)
)}
</td>
<td>
<Button className="noBackground noBorder">
<ActionLogoStyle
src={AddLogo}
/>
</Button>
<Button
className="noBackground noBorder"
onClick={() =>
modifyHeat(heat)
}
>
<ActionLogoStyle
src={ModifyLogo}
/>
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</div>
)}
</Container>
)
}
export default HeatList
感谢您的帮助。
谢谢布伦丹,
这真是个好东西post,帮助我找到了解决方案。
最终挂钩:
const dataFetchReducer = (state, action) => {
switch (action.type) {
case 'FETCH_INIT':
return {
...state,
isLoading: true,
isError: false,
}
case 'FETCH_SUCCESS':
return {
...state,
isLoading: false,
isError: false,
data: action.payload,
}
case 'FETCH_FAILURE':
return {
...state,
isLoading: false,
isError: true,
}
default:
throw new Error()
}
}
export const useAxios = (initialUrl, method, initialData) => {
const [url, setUrl] = useState(initialUrl)
const [state, dispatch] = useReducer(dataFetchReducer, {
isLoading: false,
isError: false,
data: initialData,
})
useEffect(() => {
let didCancel = false
const params = {
method: method,
url: url,
headers: { accept: '*/*' },
data: initialData,
}
const fetchData = async (params) => {
dispatch({ type: 'FETCH_INIT' })
console.log('in axios', method, url, params)
try {
const result = await axios(params)
// console.log('result', result)
if (!didCancel) {
dispatch({ type: 'FETCH_SUCCESS', payload: result.data })
}
} catch (error) {
if (!didCancel) {
dispatch({ type: 'FETCH_FAILURE' })
}
}
}
url && fetchData(params)
return () => {
didCancel = true
}
}, [initialData, method, url])
return [state, setUrl]
}
最终模态:
export default function HeatModal({
isShow,
triggerModal,
activeHeat,
setActiveHeat,
saveHeat,
}) {
function save() {
saveHeat()
triggerModal()
}
return (
<>
<Modal show={isShow} onHide={triggerModal}>
<Modal.Header>
<Modal.Title>{activeHeat.name}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<FormGroup as={Row}>
<FormLabel column>
Nouvelle date de chaleur
</FormLabel>
<Col>
<MyDatePicker
field={'date'}
value={activeHeat.date}
setter={setActiveHeat}
/>
</Col>
</FormGroup>
</Form>
</Modal.Body>
<Modal.Footer as={NavContainer}>
<Button variant="outline-success" onClick={triggerModal}>
Annuler
</Button>
<Button variant="success" onClick={save}>
Confirmer
</Button>
</Modal.Footer>
</Modal>
</>
)
}
最终名单:
const HeatList = () => {
const heat = {
idHeat: -1,
name: '',
date: new Date(),
idDog: -1,
}
const [heatsWithName, setHeatsWithNames] = useState([])
const [heatPerPage, setHeatPerPage] = useState(10)
const [firstHeat, setFirstHeat] = useState(0)
const [showModal, setShowModal] = useState(false)
const [activeHeat, setActiveHeat] = useState(heat)
const [heatToSave, setHeatToSave] = useState(undefined)
const [{ data: dogs, isLoading: dogsIsLoading }] = useAxios(
'/dogs',
'GET',
null
)
const [{ data: editResponse, isLoading: editLoading }, setEditUrl] =
useAxios('', 'PUT', heatToSave)
const [{ data: heats, isLoading: heatsIsLoading }] = useAxios(
'/heats',
'GET',
editResponse
)
useEffect(() => {
if (
editResponse &&
activeHeat.idHeat === editResponse.idHeat &&
editResponse > 0
) {
console.log('in use Effect2')
toastSuccess(SAVE_SUCCESS)
} else if (editResponse === '') {
console.log('in use Effect3')
toastError(SAVE_ERROR)
}
}, [activeHeat.idHeat, editResponse])
useEffect(() => {
console.log('in new heats array', heats, 'dogs', dogs)
let newHeatsArr = []
let dogList = []
if (heats && dogs && Array.isArray(heats)) {
dogList = dogs
.filter(({ gender }) => gender === 'Femelle')
.filter(({ status }) => status === 'Élevage')
.filter(({ state }) => state === 'Vivant')
// console.log('in if', dogList)
dogList.map((d) =>
newHeatsArr.push({
idDog: d.idDog,
name: d.name,
idHeat: heats.find((h) => d.idDog === h.idDog)
? heats.find((h) => d.idDog === h.idDog).idHeat
: -1,
date: heats.find((h) => d.idDog === h.idDog)
? heats.find((h) => d.idDog === h.idDog).date
: 'Jamais',
})
)
}
setHeatsWithNames(newHeatsArr)
console.log('newHeatsArray', newHeatsArr)
}, [heats, dogs])
const { items, requestSort, sortConfig } = useSortableData(heatsWithName)
const getClassNamesFor = (name) => {
if (!sortConfig) {
return
}
return sortConfig.key === name ? sortConfig.direction : undefined
}
const triggerModal = () => {
setShowModal((prev) => !prev)
}
const modifyHeat = (h) => {
setActiveHeat(h)
triggerModal()
}
const saveHeat = () => {
console.log('aH', activeHeat)
setEditUrl('/heat/' + activeHeat.idHeat)
setHeatToSave(activeHeat)
}
return (
<Container>
{heatsIsLoading || dogsIsLoading ? (
<Spinner animation="border" variant="primary" />
) : (
<div className="table-container">
<h1 className="text-center">Liste des chaleurs</h1>
<HeatModal
isShow={showModal}
triggerModal={triggerModal}
activeHeat={activeHeat}
setActiveHeat={setActiveHeat}
saveHeat={saveHeat}
/>
<Paginator
items={items}
dogPerPage={heatPerPage}
setDogPerPage={setHeatPerPage}
firstDog={firstHeat}
setFirstDog={setFirstHeat}
/>
<Table
striped
bordered
hover
responsive
className="table-fixed"
>
<thead>
<tr>
<th>
<button
type="buttton"
onClick={() => requestSort('name')}
className={getClassNamesFor('name')}
>
Nom
</button>
</th>
<th>
<button
type="buttton"
onClick={() => requestSort('date')}
className={getClassNamesFor('date')}
>
Date dernière chaleur
</button>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{items &&
items
.slice(
firstHeat,
Number(firstHeat) + Number(heatPerPage)
)
.map((heat) => (
<tr key={heat.idDog}>
<td>{heat.name}</td>
<td>
{heat.date === 'Jamais'
? 'Jamais'
: formatDate().format(
new Date(heat.date)
)}
</td>
<td>
<Button className="noBackground noBorder">
<ActionLogoStyle
src={AddLogo}
/>
</Button>
<Button
className="noBackground noBorder"
disabled={
heat.date === 'Jamais'
}
onClick={() =>
modifyHeat(heat)
}
>
<ActionLogoStyle
src={ModifyLogo}
/>
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</div>
)}
</Container>
)
}
export default HeatList
我有一个 table 可以在页面加载时完美运行,该页面还包含一个模态组件来更新 table 的一行,我正在使用自定义挂钩来制作 API 调用并且效果很好。
问题是修改了一行后,没找到刷新table的方法。 DB 得到更新,Toast 显示更新成功,对新列表的调用被触发并在 DBHook 中使用 console.log('Result', result) 获得新列表但是,具有加热依赖性的 useEffect 从不被解雇。
如果我转到另一个页面然后返回或按 F5,列表会正确刷新。
dbHook :
export const useAxios = (url, method, data) => {
const [responseData, setResponseData] = useState(undefined)
const [status, setStatus] = useState(undefined)
const [error, setError] = useState('')
const [loading, setLoading] = useState(true)
const params = {
method: method,
url: url,
headers: { accept: '*/*' },
data: data,
}
const fetchData = async (params) => {
//console.log('in axios', method, url, data)
try {
const result = await axios.request(params)
//console.log('Result', result)
setResponseData(result.data)
setStatus(result.status)
//console.log('resultStatus', result.status)
} catch (error) {
setError(error.response)
//console.log('Error', error)
} finally {
setLoading(false)
//console.log('axios finished', url)
}
}
useEffect(() => {
fetchData(params)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url])
return { responseData, error, loading, status }
}
模态:
export default function HeatModal({
isShow,
triggerModal,
activeHeat,
setActiveHeat,
saveHeat,
}) {
function save() {
saveHeat()
triggerModal()
}
return (
<>
<Modal show={isShow} onHide={triggerModal}>
<Modal.Header>
<Modal.Title>{activeHeat.name}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<FormGroup as={Row}>
<FormLabel column>
Nouvelle date de chaleur
</FormLabel>
<Col>
<MyDatePicker
field={'date'}
value={activeHeat.date}
setter={setActiveHeat}
/>
</Col>
</FormGroup>
</Form>
</Modal.Body>
<Modal.Footer as={NavContainer}>
<Button variant="outline-success" onClick={triggerModal}>
Annuler
</Button>
<Button variant="success" onClick={save}>
Confirmer
</Button>
</Modal.Footer>
</Modal>
</>
)
}
列表:
const HeatList = () => {
const [heatsUrl, setHeatsUrl] = useState('/heats')
const heat = {
idHeat: -1,
name: '',
date: new Date(),
idDog: -1,
}
const [heatsWithName, setHeatsWithNames] = useState([])
const [heatPerPage, setHeatPerPage] = useState(10)
const [firstHeat, setFirstHeat] = useState(0)
const [showModal, setShowModal] = useState(false)
const [activeHeat, setActiveHeat] = useState(heat)
const [editUrl, setEditUrl] = useState('')
const {
responseData: heats,
loading: heatsIsLoading,
error: heatsIsError,
} = useAxios(heatsUrl, 'GET', null)
const { responseData: dogs, loading: dogsIsLoading } = useAxios(
'/dogs',
'GET',
null
)
const { responseData: editResponse, loading: editLoading } = useAxios(
editUrl,
'PUT',
activeHeat
)
useEffect(() => {
console.log('activeHeat', activeHeat.idHeat)
editResponse && console.log('editResponse', editResponse.idHeat)
if (editResponse && activeHeat.idHeat === editResponse.idHeat) {
console.log('in use Effect2')
setActiveHeat(editResponse)
toastSuccess(SAVE_SUCCESS)
setHeatsUrl('/heats')
} else if (editResponse === '') {
console.log('in use Effect3')
toastError(SAVE_ERROR)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [editResponse])
useEffect(() => {
console.log('in new heats array')
let newHeatsArr = []
if (heats && dogs) {
console.log('in if', heats)
heats.map((h) => newHeatsArr.push(buildHeat(h, true)))
}
setHeatsWithNames(newHeatsArr)
console.log('newHeatsArray', newHeatsArr)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [heats, dogs])
const { items, requestSort, sortConfig } = useSortableData(heatsWithName)
const getClassNamesFor = (name) => {
if (!sortConfig) {
return
}
return sortConfig.key === name ? sortConfig.direction : undefined
}
const triggerModal = () => {
setShowModal((prev) => !prev)
}
function buildHeat(origHeat, withName) {
const newHeat = {
idHeat: origHeat.idHeat,
date: origHeat.date,
idDog: origHeat.idDog,
}
if (withName) {
let dogName =
dogs && dogs.find((d) => d.idDog === origHeat.idDog).name
Object.assign(newHeat, dogName && { name: dogName })
}
return newHeat
}
const modifyHeat = (h) => {
setActiveHeat(h)
triggerModal()
}
const saveHeat = () => {
console.log('aH', activeHeat)
setEditUrl('/heat/' + activeHeat.idHeat)
}
return (
<Container>
{heatsIsLoading || dogsIsLoading ? (
<Spinner animation="border" variant="primary" />
) : (
<div className="table-container">
<h1 className="text-center">Liste des chaleurs</h1>
<HeatModal
isShow={showModal}
triggerModal={triggerModal}
activeHeat={activeHeat}
setActiveHeat={setActiveHeat}
saveHeat={saveHeat}
/>
<Paginator
items={items}
dogPerPage={heatPerPage}
setDogPerPage={setHeatPerPage}
firstDog={firstHeat}
setFirstDog={setFirstHeat}
/>
<Table
striped
bordered
hover
responsive
className="table-fixed"
>
<thead>
<tr>
<th>
<button
type="buttton"
onClick={() => requestSort('name')}
className={getClassNamesFor('name')}
>
Nom
</button>
</th>
<th>
<button
type="buttton"
onClick={() => requestSort('date')}
className={getClassNamesFor('date')}
>
Date dernière chaleur
</button>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{items &&
items
.slice(
firstHeat,
Number(firstHeat) + Number(heatPerPage)
)
.map((heat) => (
<tr key={heat.idHeat}>
<td>{heat.name}</td>
<td>
{formatDate().format(
new Date(heat.date)
)}
</td>
<td>
<Button className="noBackground noBorder">
<ActionLogoStyle
src={AddLogo}
/>
</Button>
<Button
className="noBackground noBorder"
onClick={() =>
modifyHeat(heat)
}
>
<ActionLogoStyle
src={ModifyLogo}
/>
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</div>
)}
</Container>
)
}
export default HeatList
感谢您的帮助。
谢谢布伦丹,
这真是个好东西post,帮助我找到了解决方案。
最终挂钩:
const dataFetchReducer = (state, action) => {
switch (action.type) {
case 'FETCH_INIT':
return {
...state,
isLoading: true,
isError: false,
}
case 'FETCH_SUCCESS':
return {
...state,
isLoading: false,
isError: false,
data: action.payload,
}
case 'FETCH_FAILURE':
return {
...state,
isLoading: false,
isError: true,
}
default:
throw new Error()
}
}
export const useAxios = (initialUrl, method, initialData) => {
const [url, setUrl] = useState(initialUrl)
const [state, dispatch] = useReducer(dataFetchReducer, {
isLoading: false,
isError: false,
data: initialData,
})
useEffect(() => {
let didCancel = false
const params = {
method: method,
url: url,
headers: { accept: '*/*' },
data: initialData,
}
const fetchData = async (params) => {
dispatch({ type: 'FETCH_INIT' })
console.log('in axios', method, url, params)
try {
const result = await axios(params)
// console.log('result', result)
if (!didCancel) {
dispatch({ type: 'FETCH_SUCCESS', payload: result.data })
}
} catch (error) {
if (!didCancel) {
dispatch({ type: 'FETCH_FAILURE' })
}
}
}
url && fetchData(params)
return () => {
didCancel = true
}
}, [initialData, method, url])
return [state, setUrl]
}
最终模态:
export default function HeatModal({
isShow,
triggerModal,
activeHeat,
setActiveHeat,
saveHeat,
}) {
function save() {
saveHeat()
triggerModal()
}
return (
<>
<Modal show={isShow} onHide={triggerModal}>
<Modal.Header>
<Modal.Title>{activeHeat.name}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<FormGroup as={Row}>
<FormLabel column>
Nouvelle date de chaleur
</FormLabel>
<Col>
<MyDatePicker
field={'date'}
value={activeHeat.date}
setter={setActiveHeat}
/>
</Col>
</FormGroup>
</Form>
</Modal.Body>
<Modal.Footer as={NavContainer}>
<Button variant="outline-success" onClick={triggerModal}>
Annuler
</Button>
<Button variant="success" onClick={save}>
Confirmer
</Button>
</Modal.Footer>
</Modal>
</>
)
}
最终名单:
const HeatList = () => {
const heat = {
idHeat: -1,
name: '',
date: new Date(),
idDog: -1,
}
const [heatsWithName, setHeatsWithNames] = useState([])
const [heatPerPage, setHeatPerPage] = useState(10)
const [firstHeat, setFirstHeat] = useState(0)
const [showModal, setShowModal] = useState(false)
const [activeHeat, setActiveHeat] = useState(heat)
const [heatToSave, setHeatToSave] = useState(undefined)
const [{ data: dogs, isLoading: dogsIsLoading }] = useAxios(
'/dogs',
'GET',
null
)
const [{ data: editResponse, isLoading: editLoading }, setEditUrl] =
useAxios('', 'PUT', heatToSave)
const [{ data: heats, isLoading: heatsIsLoading }] = useAxios(
'/heats',
'GET',
editResponse
)
useEffect(() => {
if (
editResponse &&
activeHeat.idHeat === editResponse.idHeat &&
editResponse > 0
) {
console.log('in use Effect2')
toastSuccess(SAVE_SUCCESS)
} else if (editResponse === '') {
console.log('in use Effect3')
toastError(SAVE_ERROR)
}
}, [activeHeat.idHeat, editResponse])
useEffect(() => {
console.log('in new heats array', heats, 'dogs', dogs)
let newHeatsArr = []
let dogList = []
if (heats && dogs && Array.isArray(heats)) {
dogList = dogs
.filter(({ gender }) => gender === 'Femelle')
.filter(({ status }) => status === 'Élevage')
.filter(({ state }) => state === 'Vivant')
// console.log('in if', dogList)
dogList.map((d) =>
newHeatsArr.push({
idDog: d.idDog,
name: d.name,
idHeat: heats.find((h) => d.idDog === h.idDog)
? heats.find((h) => d.idDog === h.idDog).idHeat
: -1,
date: heats.find((h) => d.idDog === h.idDog)
? heats.find((h) => d.idDog === h.idDog).date
: 'Jamais',
})
)
}
setHeatsWithNames(newHeatsArr)
console.log('newHeatsArray', newHeatsArr)
}, [heats, dogs])
const { items, requestSort, sortConfig } = useSortableData(heatsWithName)
const getClassNamesFor = (name) => {
if (!sortConfig) {
return
}
return sortConfig.key === name ? sortConfig.direction : undefined
}
const triggerModal = () => {
setShowModal((prev) => !prev)
}
const modifyHeat = (h) => {
setActiveHeat(h)
triggerModal()
}
const saveHeat = () => {
console.log('aH', activeHeat)
setEditUrl('/heat/' + activeHeat.idHeat)
setHeatToSave(activeHeat)
}
return (
<Container>
{heatsIsLoading || dogsIsLoading ? (
<Spinner animation="border" variant="primary" />
) : (
<div className="table-container">
<h1 className="text-center">Liste des chaleurs</h1>
<HeatModal
isShow={showModal}
triggerModal={triggerModal}
activeHeat={activeHeat}
setActiveHeat={setActiveHeat}
saveHeat={saveHeat}
/>
<Paginator
items={items}
dogPerPage={heatPerPage}
setDogPerPage={setHeatPerPage}
firstDog={firstHeat}
setFirstDog={setFirstHeat}
/>
<Table
striped
bordered
hover
responsive
className="table-fixed"
>
<thead>
<tr>
<th>
<button
type="buttton"
onClick={() => requestSort('name')}
className={getClassNamesFor('name')}
>
Nom
</button>
</th>
<th>
<button
type="buttton"
onClick={() => requestSort('date')}
className={getClassNamesFor('date')}
>
Date dernière chaleur
</button>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{items &&
items
.slice(
firstHeat,
Number(firstHeat) + Number(heatPerPage)
)
.map((heat) => (
<tr key={heat.idDog}>
<td>{heat.name}</td>
<td>
{heat.date === 'Jamais'
? 'Jamais'
: formatDate().format(
new Date(heat.date)
)}
</td>
<td>
<Button className="noBackground noBorder">
<ActionLogoStyle
src={AddLogo}
/>
</Button>
<Button
className="noBackground noBorder"
disabled={
heat.date === 'Jamais'
}
onClick={() =>
modifyHeat(heat)
}
>
<ActionLogoStyle
src={ModifyLogo}
/>
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</div>
)}
</Container>
)
}
export default HeatList