I try not to use export default because people can rename the component when they import it, which leads to all sorts of headaches when you refactor later. Suggest only using named exports.
We've been moving away from moment.js to https://date-fns.org/ at Voltus. I like it because you only ever work with string or Date objects, whereas moment makes you create these weird mutable moment.Moment objects.
const [priorities, setPriorities] = useState<Array<DailyPriority>>([...])
// I find this style of array types easier to read since it's fewer characters
const [priorities, setPriorities] = useState<DailyPriority[]>([...])
const [loadingPriorities, setLoadingPriorities] = useState<boolean>(true);
// You don't need to pass `boolean` generics to `useState` since it can infer the type
// Also recommend renaming booleans to `is*`
const [isLoadingPriorities, setIsLoadingPriorities] = useState(true);
I'd really recommend using react-query to manage your data loading. It is so good and makes dealing with stuff like this a lot easier.
The way you're setting priorities is similar to how I did it in my DnD character sheet (wait a sec after the user types to sync to the network). I think that approach works ok but it leaves room for losing data. I'm curious how a service like GitHub manages when you're typing in the PR review window and hit refresh? react-query has some things for synching to localstorage/indexeddb but I've never tried to use them. But if you just use react-query for your data fetching and mutating, it will handle setting all of your loading states so you don't have to manage that yourself.
People complain about axios, but I like it for stuff like this because you can set global config/middleware so all your auth stuff can be handled in one place and you don't have to repeat it in your queries. Alternatively you can write a fetch wrapper that always adds the bearer token to your requests.
If you do end up using react-query, you'll probably end up turning functions like this into custom hooks. This blog post is a good primer and has a nice example of what I mean. Typically in our code we get and mutate like this:
// useFacilitiesQuery.tsx
const fetchFacilities = (): Facilities => {
return fetch('/api/facilities')
}
export const useFacilitiesQuery = () => {
return useQuery({
queryKey: ['facilities'], <-- this is a cache key for react-query. You can invalidate it to make it refetch your data.
queryFn: fetchFacilities
})
}
// App.tsx
// Get some facilities
const {data, isLoading} = useFacilitiesQuery()
// Or get a single facility
const {data, isLoading} = useFacilityQuery({ facilityId })
// Mutate a facility
const queryClient = useQueryClient() <-- this is how you manage react-query's cache
const mutation = useFacilityMutation()
const handleClick = () => {
mutation.mutate(facilityId, {
onSuccess: () => Toast.success(`You mutated facility ${facilityId}`),
onSettled: () => {
queryClient.invalidateQueries(['facilities']) <-- this will make react-query refetch all of your facilities queries
}
})
}
return <button onClick={handleClick}>Mutate the thing</button>
I try not to use
export default
because people can rename the component when they import it, which leads to all sorts of headaches when you refactor later. Suggest only using named exports.We've been moving away from moment.js to https://date-fns.org/ at Voltus. I like it because you only ever work with string or Date objects, whereas moment makes you create these weird mutable moment.Moment objects.
I'd really recommend using react-query to manage your data loading. It is so good and makes dealing with stuff like this a lot easier.
The way you're setting priorities is similar to how I did it in my DnD character sheet (wait a sec after the user types to sync to the network). I think that approach works ok but it leaves room for losing data. I'm curious how a service like GitHub manages when you're typing in the PR review window and hit refresh? react-query has some things for synching to localstorage/indexeddb but I've never tried to use them. But if you just use react-query for your data fetching and mutating, it will handle setting all of your loading states so you don't have to manage that yourself.
People complain about axios, but I like it for stuff like this because you can set global config/middleware so all your auth stuff can be handled in one place and you don't have to repeat it in your queries. Alternatively you can write a fetch wrapper that always adds the bearer token to your requests.
If you do end up using react-query, you'll probably end up turning functions like this into custom hooks. This blog post is a good primer and has a nice example of what I mean. Typically in our code we get and mutate like this: