Refactor hooks with useEntityRequest

develop^2
Alex Gleason 2023-03-23 16:22:15 -05:00
rodzic 45c12e9b65
commit aa7e2f6965
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
4 zmienionych plików z 26 dodań i 41 usunięć

Wyświetl plik

@ -1,10 +1,10 @@
import { useState } from 'react';
import { z } from 'zod';
import { useApi, useAppDispatch } from 'soapbox/hooks';
import { useAppDispatch } from 'soapbox/hooks';
import { importEntities } from '../actions';
import { useEntityRequest } from './useEntityRequest';
import { parseEntitiesPath, toAxiosRequest } from './utils';
import type { Entity } from '../types';
@ -16,21 +16,18 @@ interface UseCreateEntityOpts<TEntity extends Entity = Entity> {
function useCreateEntity<TEntity extends Entity = Entity, Data = any>(
expandedPath: ExpandedEntitiesPath,
request: EntityRequest,
entityRequest: EntityRequest,
opts: UseCreateEntityOpts<TEntity> = {},
) {
const api = useApi();
const dispatch = useAppDispatch();
const [isLoading, setIsLoading] = useState<boolean>(false);
const { request, isLoading } = useEntityRequest();
const { entityType, listKey } = parseEntitiesPath(expandedPath);
async function createEntity(data: Data, callbacks: EntityCallbacks<TEntity> = {}): Promise<void> {
setIsLoading(true);
try {
const result = await api.request({
...toAxiosRequest(request),
const result = await request({
...toAxiosRequest(entityRequest),
data,
});
@ -48,8 +45,6 @@ function useCreateEntity<TEntity extends Entity = Entity, Data = any>(
callbacks.onError(error);
}
}
setIsLoading(false);
}
return {

Wyświetl plik

@ -1,9 +1,8 @@
import { useState } from 'react';
import { useApi, useAppDispatch, useGetState } from 'soapbox/hooks';
import { useAppDispatch, useGetState } from 'soapbox/hooks';
import { deleteEntities, importEntities } from '../actions';
import { useEntityRequest } from './useEntityRequest';
import { toAxiosRequest } from './utils';
import type { EntityCallbacks, EntityRequest } from './types';
@ -15,16 +14,13 @@ import type { EntityCallbacks, EntityRequest } from './types';
*/
function useDeleteEntity(
entityType: string,
request: EntityRequest,
entityRequest: EntityRequest,
) {
const api = useApi();
const dispatch = useAppDispatch();
const getState = useGetState();
const [isLoading, setIsLoading] = useState<boolean>(false);
const { request, isLoading } = useEntityRequest();
async function deleteEntity(entityId: string, callbacks: EntityCallbacks<string> = {}): Promise<void> {
setIsLoading(true);
// Get the entity before deleting, so we can reverse the action if the API request fails.
const entity = getState().entities[entityType]?.store[entityId];
@ -33,10 +29,10 @@ function useDeleteEntity(
try {
// HACK: replace occurrences of `:id` in the URL. Maybe there's a better way?
const axiosReq = toAxiosRequest(request);
const axiosReq = toAxiosRequest(entityRequest);
axiosReq.url?.replaceAll(':id', entityId);
await api.request(axiosReq);
await request(axiosReq);
// Success - finish deleting entity from the state.
dispatch(deleteEntities([entityId], entityType));
@ -54,8 +50,6 @@ function useDeleteEntity(
callbacks.onError(e);
}
}
setIsLoading(false);
}
return {

Wyświetl plik

@ -2,13 +2,14 @@ import { useEffect } from 'react';
import z from 'zod';
import { getNextLink, getPrevLink } from 'soapbox/api';
import { useApi, useAppDispatch, useAppSelector, useGetState } from 'soapbox/hooks';
import { useAppDispatch, useAppSelector, useGetState } from 'soapbox/hooks';
import { filteredArray } from 'soapbox/schemas/utils';
import { realNumberSchema } from 'soapbox/utils/numbers';
import { entitiesFetchFail, entitiesFetchRequest, entitiesFetchSuccess, invalidateEntityList } from '../actions';
import { parseEntitiesPath, toAxiosRequest } from './utils';
import { useEntityRequest } from './useEntityRequest';
import { parseEntitiesPath } from './utils';
import type { Entity, EntityListState } from '../types';
import type { EntitiesPath, EntityRequest, EntitySchema, ExpandedEntitiesPath } from './types';
@ -32,11 +33,11 @@ function useEntities<TEntity extends Entity>(
/** Tells us where to find/store the entity in the cache. */
expandedPath: ExpandedEntitiesPath,
/** API route to GET, eg `'/api/v1/notifications'`. If undefined, nothing will be fetched. */
request: EntityRequest,
entityRequest: EntityRequest,
/** Additional options for the hook. */
opts: UseEntitiesOpts<TEntity> = {},
) {
const api = useApi();
const { request } = useEntityRequest();
const dispatch = useAppDispatch();
const getState = useGetState();
@ -61,7 +62,7 @@ function useEntities<TEntity extends Entity>(
dispatch(entitiesFetchRequest(entityType, listKey));
try {
const response = await api.request(toAxiosRequest(req));
const response = await request(req);
const schema = opts.schema || z.custom<TEntity>();
const entities = filteredArray(schema).parse(response.data);
const parsedCount = realNumberSchema.safeParse(response.headers['x-total-count']);
@ -82,7 +83,7 @@ function useEntities<TEntity extends Entity>(
};
const fetchEntities = async(): Promise<void> => {
await fetchPage(request, true);
await fetchPage(entityRequest, true);
};
const fetchNextPage = async(): Promise<void> => {
@ -112,7 +113,7 @@ function useEntities<TEntity extends Entity>(
if (isInvalid || isUnset || isStale) {
fetchEntities();
}
}, [request, isEnabled]);
}, [entityRequest, isEnabled]);
return {
entities,

Wyświetl plik

@ -1,11 +1,11 @@
import { useEffect, useState } from 'react';
import { useEffect } from 'react';
import z from 'zod';
import { useApi, useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { importEntities } from '../actions';
import { toAxiosRequest } from './utils';
import { useEntityRequest } from './useEntityRequest';
import type { Entity } from '../types';
import type { EntitySchema, EntityPath, EntityRequest } from './types';
@ -20,10 +20,10 @@ interface UseEntityOpts<TEntity extends Entity> {
function useEntity<TEntity extends Entity>(
path: EntityPath,
request: EntityRequest,
entityRequest: EntityRequest,
opts: UseEntityOpts<TEntity> = {},
) {
const api = useApi();
const { request, isLoading: isFetching } = useEntityRequest();
const dispatch = useAppDispatch();
const [entityType, entityId] = path;
@ -33,21 +33,16 @@ function useEntity<TEntity extends Entity>(
const entity = useAppSelector(state => state.entities[entityType]?.store[entityId] as TEntity | undefined);
const [isFetching, setIsFetching] = useState(false);
const isLoading = isFetching && !entity;
const fetchEntity = async () => {
setIsFetching(true);
try {
const response = await api.request(toAxiosRequest(request));
const response = await request(entityRequest);
const entity = schema.parse(response.data);
dispatch(importEntities([entity], entityType));
} catch (e) {
// do nothing
}
setIsFetching(false);
};
useEffect(() => {