我已经努力了好几个小时。当我第一次加载组件时,表为空。当我在页面之间导航并返回到组件时,该表会正确显示数据,但是在组件的第一次渲染时,即使在控制台中更改了properlist,似乎仍认为vehicleList为空。我什至试图用useEffect钩子强制重新渲染,并且具有vehicleList依赖关系,但是它不起作用。我已经阅读了很多关于不变性和引用的文章,但是即使我尝试在将[... vehicleList]传递到表之前对其进行结构分解时,它也不会触发使用正确道具的重新渲染。
const VehiclesList = ({loading, setLoading, vehicleList, categoryList, setActiveMenuItem, setMountVehicleDetails, highlightRow}) => {
const router = useRouter();
const { status } = router.query;
const [reloadPage, setReloadPage] = useState(false)
useEffect(()=> {
setReloadPage(!reloadPage)
}, [vehicleList])
return (
<div className={classes.VehiclesList}>
{loading ? null :
<>
<HeadCard
color="#DE5C5C"
background="#fff"
title={
<div className={classes.NavigationContainer}>
{<NavigationBtn
title={'Toutes catégories'}
width={'100px'}
height={'50px'}
category={'all'}
/>}
{categoryList && categoryList.data ? categoryList.data.map((element, index) => {
return <NavigationBtn
key={index}
title={categoryList.data[index].data.name}
category={categoryList.data[index].data.name}
width={'50px'}
height={'50px'}
/>
}
) : null}
</div>
}
icon='key'
loading={loading}
/>
<Row>
<Col md="12">
<Card className="main-card mb-3">
<CardBody>
<ReactTable data={vehicleList? vehicleList : []}
columns={[
{
Header: "Informations",
columns: [
{
Header: '',
id: 'photo',
accessor: (d) => <img src={d.pictures.length > 0 ? d.pictures[0].medium_url : 'https://static.teteamodeler.com/media/cache/thumb_400/coloriage-voitures.png'} alt = 'photo de la voiture' className={classes.Photo}/>,
},
{
Header: "Marque",
id: 'brand',
maxWidth: 80,
accessor: (d) => d.brand,
},
{
Header: "Modèle",
id: 'model',
sortable: false,
accessor: (d) => d.model,
},
{
Header: "Catégorie",
id: 'category',
accessor: (d) => d.category.name,
}
,
{
Header: "Registration",
id: 'immatriculation',
accessor: (d) => d.registration_number,
},
{
Header: "Id",
id: 'id',
maxWidth: 80,
accessor: (d) => d.id,
},
],
}
]}
defaultPageSize={vehicleList.length <=20 ? vehicleList.length : 20}
loading={loading}
loadingText="Chargement..."
nextText="Suivant"
previousText="Précédent"
noDataText="Aucune données correspondantes"
showPageSizeOptions={false}
className="-striped -highlight"
getTdProps={(state, rowInfo, column, instance) => {
if(rowInfo !== undefined) {
return {
style: {
background: rowInfo.row.id === highlightRow ? '#DE5C5C' : ''
},
onClick: (e) => {
console.log('A Td Element was clicked!')
console.log('it produced this event:', e)
console.log('It was in this column:', column)
console.log('It was in this row:', rowInfo)
console.log('It was in this table instance:', instance)
router.push(`/vehicles?status=vehicle_details&vehicle_id=${rowInfo.row.id}`)
setActiveMenuItem(status)
setMountVehicleDetails(true)
setLoading(true)
}
}
} else {
return {}
}
}}
/>
</CardBody>
</Card>
</Col>
</Row>
</>
}
</div>
)
}
export default VehiclesList;
父组件是:
const Vehicles = () => {
//Data from route and localStorage
const router = useRouter();
const { status, category, vehicle_id } = router.query;
const [activeMenuItem, setActiveMenuItem] = useState('categories_list');
const [loading, setLoading] = useState(false);
const [reloadPage, setReloadPage] = useState(false);
const [highlightRow, setHighlightRow] = useState('');
//Constant to start fetching
const [mountVehicleList, setMountVehicleList] = useState(false);
//Data from useSwr hooks
const [vehicleList, setVehicleList] = useState([]);
const session = new SessionService();
const { dataFromFetch, error } = useSWR(mountVehicleList ? `${session.domain}/admin/vehicle/list` : null, url =>
session.fetch(url, {
method: 'POST',
body: JSON.stringify({
parametersToCheck: {limit: 0}
})
})
,
{
onSuccess: (dataFromFetch) => {
setVehicleList(dataFromFetch)
setMountVehicleList(false)
setLoading(false)
},
onError: (err, key, config) => {
console.log("error", err)
}
}
)
useEffect(()=> {
setLoading(true)
setMountVehicleList(true)
// router.push('/vehicles?status=categories_list')
}, [])
useEffect(() => {
setActiveMenuItem(category? `${status}/category/${category}` : status);
}, [status, category]);
useEffect(()=> {
console.log('passed in useEffect reload page')
setLoading(true)
setMountDataForRateManagement(true)
}, [reloadPage])
const backArrowHandler = () => {
router.back();
}
const menu = [
{
item: 'categories_list',
label: 'Liste des catégories',
route: '/vehicles?status=categories_list'
},
{
item: category ? `${status}/category/${category}` : 'vehicles_list/category/all',
label: 'Liste des voitures',
route: category ? `/vehicles?status=vehicles_list&category=${category}` : '/vehicles?status=vehicles_list&category=all'
},
{
item: 'agencies_list',
label: 'Liste des agences',
route: '/vehicles?status=agencies_list'
},
{
item: 'bookings_parameters',
label: 'Paramètres des réservations',
route: '/vehicles?status=bookings_parameters'
},
{
item: 'rate_management',
label: 'Gestion des tarifs',
route: '/vehicles?status=rate_management'
},
];
const carMenu = [
{
item: 'vehicle_details',
label: 'Détails véhicule',
route: 'vehicles?status=vehicle_details',
},
{
item: 'vehicle_calendar',
label: 'Calendrier du véhicule',
route: 'vehicles?status=vehicle_calendar'
}
]
const renderSwitch = (param) => {
const vehicleListPerCategory = vehicleList && vehicleList.vehicleList ? vehicleList.vehicleList.data.filter(element => element.zc_category.name === category) : [];
switch(param) {
case 'categories_list':
return <div style={{width: '75vw'}}>
<CategoryList
setLoading={setLoading}
categoryList={categoryList}
/>
</div>
case 'bookings_parameters':
return <BookingParameters />
case `vehicles_list/category/${category}`:
return <div style={{width: '75vw'}}>
<VehiclesList
categoryList={categoryList}
category={category}
loading={loading}
vehicleList={category === 'all' && vehicleList.vehicleList ? [...vehicleList.vehicleList.data] : [...vehicleListPerCategory]}
setActiveMenuItem={setActiveMenuItem}
setMountVehicleDetails={setMountVehicleDetails}
setLoading={setLoading}
highlightRow={highlightRow}
/>
</div>
case 'rate_management':
return <div style={{width: '75vw', overflowX: 'scroll'}}>
<RateManagement
loading={loading}
setLoading={setLoading}
degressionTimes={degressionTimes}
categoryItems={categoryItems}
reloadPage={reloadPage}
setReloadPage={setReloadPage}
/>
</div>
case 'vehicle_details':
return <div style={{width: '75vw', overflowX: 'scroll'}}>
<VehicleDetails
categoryList={categoryList}
dataForSelects={dataForSelects}
vehicleDetails={vehicleDetails}
vehicleBrandsAndModels={vehicleBrandsAndModels}
setLoading={setLoading}
setMountVehicleList={setMountVehicleList}
setHighlightRow={setHighlightRow}
/>
</div>
return
default:
return '';
}
}
return (
<Layout activeNav="vehicles">
{renderSwitch(activeMenuItem)}
</Layout>
)
}
export default protect(Vehicles)
vehicleList是父组件的道具,是从api获取的。因此,它基本上等于第一个渲染的[],但最终等于项目数组。 Kinda是nextJs和React的新手,我希望我能很好地解释我的问题。