Refactor hooks with useEntityRequest
This commit is contained in:
parent
45c12e9b65
commit
aa7e2f6965
4 changed files with 26 additions and 41 deletions
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
Loading…
Reference in a new issue