skip to Main Content

I need to access the state data using a key that I’m getting from useParams.
Like this:

export const MainPageSection = (props:MainPageSectionPropsType) => {
    const params = useParams();
    const currentSection = params.section
    const excursions:ExcursionsCollectionResponseType = 
    useSelector((state:AppRootStateType)=> state[currentSection])
 ...
}

Got an error TS2538: Type ‘undefined’ cannot be used as an index type. But I can’t use conditionals here, so I wrapped this component in a container to get check for params value there and pass it to my component. Like that:

export const MainPageSection = () => {
    const params = useParams();
    const currentSection = params.section
    if (!currentSection) return
    return <MainPageSectionChild param={currentSection} title={'Title'}/>
}
export const MainPageSectionChild = (props:MainPageSectionPropsType) => {
    const excursions:ExcursionsCollectionResponseType = useSelector((state:AppRootStateType)=> state[props.param])
    const excursion:ExcursionCollectionResponseItemType = excursions[0]

But now there’s another error:
TS7053: Element implicitly has an ‘any’ type because expression of type ‘string’ can’t be used to index type ‘EmptyObject & { excursions: ExcursionsCollectionResponseType; tours: ToursCollectionResponseType; }’.   No index signature with a parameter of type ‘string’ was found on type ‘EmptyObject & { excursions: ExcursionsCollectionResponseType; tours: ToursCollectionResponseType; }’.

UPD solved by changing root state type from this

export type AppRootStateType = ReturnType<typeof store.getState> 

to this

export type AppRootStateType = ReturnType<typeof store.getState> & { [key: string]: any }

2

Answers


  1. If I understood your problem, you are doing this because you cannot call useSelector conditionally.
    However you can call it on every component render as you have to do but with a conditional value:

    export const MainPageSection = (props:MainPageSectionPropsType) => {
      const params = useParams();
      const currentSection = params.section
      const excursions:ExcursionsCollectionResponseType | undefined = 
      useSelector(currentSection ? (state:AppRootStateType)=> state[currentSection] : () => {})
    }
    

    During the first render when currentSection is undefined, excursions will be undefined since useSelector is called with an empty function () => {}, after that when the component rerenders and currentSection get the expected value, useSelector is called with (state:AppRootStateType)=> state[currentSection] and excursions should recive the expected data.

    Now you just have to handle that

    //...
    
    if(!excursions) return null
    return (
     <>
      //...
     </>
    )
    
    Login or Signup to reply.
  2. Can you show me how you configured the store and defined the AppRootStateType type ? If you followed this guide correctly, you would have a useAppSelector, that does not require you to do (state: Type) => ... . Anyway, I think something is not right in the configuration of the store.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search