Recently, I have been reevaluating the state structure used in my application and encountered some challenges on how to proceed.
Initially, I had set up the following state structure for redux:
type State = {
loading: boolean
loaded: boolean
items: Array<Item>
categories: Array<Category>
}
const initialState: State = {
loading: false,
loaded: false,
items: [],
categories: [],
}
This setup was straightforward and convenient for use with selectors. The unchanging types of items
and categories
eliminated concerns about undefined values or type casting. However, when I needed to introduce additional properties that were only occasionally required, I decided to create separate types for each redux action, leading me to the current structure:
type RequestItems = {
category: Category;
items: Array<Item>;
totalCountFromServer: number;
}
export type RequestItem = {
item: Item;
}
export type RequestCategories = {
categories: Array<Category>
}
type RequestContent =
| RequestItem
| RequestItems
| RequestCategories
type State = {
loading: boolean;
loaded: boolean;
content: RequestContent | undefined
}
While this revised structure is less redundant, I am uncertain if useSelector can accurately determine the exact type. Is there a more effective way of utilizing it than what I currently have?
I feel that using state hooks here may be somewhat redundant, but by checking for 'undefined' content slides, I could potentially return a '404'.
const { content, loading, loaded } = useSelector(state => ({
content: state.suply.content,
loading: state.suply.loading,
loaded: state.suply.loaded,
}))
const [items, setItems] = useState<Items[]>([])
const [category, setCategory] = useState<Category>(Category.emptyObject)
const [totalCountFromServer, setTotalCountFromServer] = useState<number>()
useEffect(() => {
if (content) {
setItems((content as RequestItems).items)
setCategory((content as RequestItems).category)
setTotalCountFromServer((content as RequestItems).totalCountFromServer)
}
}, [content])
Alternatively, I encounter a TypeError when attempting this approach, as the selector struggles to read properties of 'undefined' (such as 'items', 'category', 'totalCountFromServer').
const { content, loading, loaded } = useSelector(state => ({
items: (state.suply.content as RequestItems).items,
category: (state.suply.content as RequestItems).category,
totalCountFromServer: (state.suply.content as RequestItems).totalCountFromServer,
loading: state.suply.loading,
loaded: state.suply.loaded,
}))
Or I could just stick with destructuring like this, which functions correctly. Although, I came across an article suggesting that using destructuring with selectors might not be the ideal method.
const { content, loading, loaded } = useSelector(state => ({
content: state.suply.content,
loading: state.suply.loading,
loaded: state.suply.loaded,
}))
const {items, category, totalCountFromServer } = (content as RequestItems);
Hence, I wonder if there exists a superior approach to handling state with Union Type content, or if reverting to my original structure is the optimal choice?