(извините за мой английский)
Я новичок в Reactjs и пытаюсь создать приложение, в котором пользователь может создавать карточки.
У карточек должна быть категория, поэтому, когда пользователь входит в меню, чтобы перечислить и создать карточки, если не создана какая-либо категория, я хочу показать фразу для доступа пользователя перед меню категории, чтобы создать категорию.
Для этого мой компонент со списком карточек получает Prop со списком категорий, и если список пуст, он показывает баннер, если нет, показывает остальную часть компонента:
type Props = {
categorias: Categoria[];
};
const TarjetasList = ({ categorias }: Props) => { ...
return (
<>
{!categorias.length ? (
<h1>Debe crear una categoria</h1>
) : (
<>
<TarjetaFilter onSubmitFilter = {handleSubmitFilter} />
<div>
{page?.content.map((tarjeta) => (
<div key = {tarjeta.id}>
<TarjetaCard tarjeta = {tarjeta} onDelete = {getTarjetas} />
</div>
))}
</div>
<Pagination
pageCount = {page ? page?.totalPages : 0}
range = {2}
onChange = {handlePageChange}
/>
</>
)}
</>
);
};
Проблема в том, что когда пользователь обращается к меню со списком карточек, он показывает баннер с фразой «Вы должны создать категорию» в течение нескольких миллисекунд, хотя «!categoria.length» имеет значение false, а затем останавливается. отобразите его, и он отобразит остальную часть компонента так, как должен, но даже если это всего на несколько миллисекунд, я хочу этого избежать. Является ли это возможным? Что я делаю не так?
вот код компонента меню открывающего список карт:
const Tarjetas = () => {
const [categorias, setCategorias] = useState<Categoria[]>([]);
const getCategorias = useCallback(() => {
const config: AxiosRequestConfig = {
method: "GET",
url: "/categorias",
withCredentials: true,
};
requestBackend(config).then((response) => {
setCategorias(response.data.content);
});
}, []);
useEffect(() => {
getCategorias();
}, [getCategorias]);
return (
<Routes>
<Route index element = {<TarjetasList categorias = {categorias} />} />
<Route path = ":tarjetaId" element = {<TarjetasForm />} />
</Routes>
);
};
Вот полный код компонента TarjetasList:
type ControlComponentsData = {
activePage: number;
filterData: TarjetaFilterData;
};
type Props = {
categorias: Categoria[];
};
const TarjetasList = ({ categorias }: Props) => {
const [page, setPage] = useState<SpringPage<Tarjeta>>();
const [controlComponentsData, setControlComponentsData] =
useState<ControlComponentsData>({
activePage: 0,
filterData: { texto: "", categoria: null },
});
const getTarjetas = useCallback(() => {
const config: AxiosRequestConfig = {
method: "GET",
url: "/tarjetas",
withCredentials: true,
params: {
page: controlComponentsData.activePage,
size: 3,
categoriaId: controlComponentsData.filterData.categoria?.id,
texto: controlComponentsData.filterData.texto,
},
};
requestBackend(config).then((response) => {
setPage(response.data);
});
}, [controlComponentsData]);
useEffect(() => {
getTarjetas();
}, [getTarjetas]);
const handlePageChange = (pageNumber: number) => {
setControlComponentsData({
activePage: pageNumber,
filterData: controlComponentsData.filterData,
});
};
const handleSubmitFilter = (data: TarjetaFilterData) => {
setControlComponentsData({
activePage: 0,
filterData: data,
});
};
return (
<>
{!categorias.length ? (
<h1>Debe crear una categoria</h1>
) : (
<>
<TarjetaFilter onSubmitFilter = {handleSubmitFilter} />
<div>
{page?.content.map((tarjeta) => (
<div key = {tarjeta.id}>
<TarjetaCard tarjeta = {tarjeta} onDelete = {getTarjetas} />
</div>
))}
</div>
<Pagination
pageCount = {page ? page?.totalPages : 0}
range = {2}
onChange = {handlePageChange}
/>
</>
)}
</>
);
};
Ваши категории categorias
изначально пусты. Пока вы их не загрузите, вы будете отображать текст.
Самое простое возможное решение — инициализировать categorias
не пустым списком, а null
:
const [categorias, setCategorias] = useState<Categoria[] | null>(null);
Затем вы можете добавить дополнительное состояние рендеринга, пока не будут загружены categorias
:
if (!categorias) {
return <h1>Cargando…</h1>
}
return (
<>
{!categorias.length ? (
<h1>Debe crear una categoria</h1>
) : (
...
Однако в идеале вы должны обрабатывать состояние загрузки, используя сложные структуры, подобные:
{ isLoading: true, error: null, categorias: [] }
Тогда вы сможете правильно различать, когда отображать индикацию загрузки и когда отображать ошибку загрузки.
Вы можете добавить состояние
loading
и установить его в значение true, когда вы вызываете API, и установить его в значение false, когда вы получите результаты. в вашем компоненте вы сначала проверите, загружается ли он, в этом случае вы можете показать индикатор, если нет, а массив пуст, вы показываете div «пожалуйста, создайте категорию»