Search code examples
reactjsreduxreact-hooksreact-reduxredux-toolkit

Why can't i return a specific propery from state in store, while it works fine when returning its parent object?


that might seem to be a little confusing but basically i just want to access a propety from the state itself using useSelector hook at any component to retrieve a specific property as follows, what i mean by that, for example, i configured my slice which has an initial state with the following structure, however it should just do fine since i use useSelector hook to get those state values from there, but it only works when i try to access only its parent object but its properties...

in my component, i have to be able to access state.filters.departureTimeRange property which im pretty sure it has already data and already tested when i printed out the state.filters itself. But i dont get whats wrong with the properties of that state object and just returns undefined when i try to print the properties inside...

to sum up: state.filters is OK but state.filters.departureTimeRange or any other property just makes me cancer, been messing around this for maybe hours but no luck! any help is so appreciated, thanks a lot in advance

My Component

const DepartureHour = () => {
  const [selectedOption, setSelectedOption] = useState('evening');
  const [departureTime, setDepartureTime] = useState<[number, number]>([0, 24]);
  const dispatch = useDispatch();
  const departureTimeRange = useSelector((state: RootState) => state.filters.departureTimeRange);
 

  useEffect(() => {
    if (departureTimeRange) {
      console.log(departureTimeRange);
    }
  }, [departureTimeRange]);

filtersSlice

interface FiltersState {

    priceRange: [number, number];
    departureTimeRange: [number, number];
    seatLayout: string;
    busCompanies: string[];
    services: string[];
    destination: string[];
    departure: string[];
  }
  
  export interface RootState {
    filters: FiltersState;
  }

  const initialState: RootState = {
    filters: {
      priceRange: [0, 1000],
      departureTimeRange: [0, 24],
      seatLayout: '',
      busCompanies: [],
      services: [],
      destination: [],
      departure: [],
    },
  };


const filtersSlice = createSlice({
    name: 'filters',
    initialState,
    reducers: {
          setDepartureTimeRange(state, action:PayloadAction<FiltersState['departureTimeRange'] >) {
            state.filters.departureTimeRange = action.payload
        },
          //other reducers
})

export const {setDepartureTimeRange} = filtersSlice.actions;

export default filtersSlice.reducer;



rootReducer


const rootReducer = combineReducers({
    seats: seatsReducer,
    selectedSeats: selectedSeatsReducer,
    filters: filtersReducer
});

export default rootReducer;




Solution

  • Hi I think you have double folding:

    You define reducer as:

    filters: filtersReducer
    

    Then you define initialState:

    const initialState: RootState = {
        filters: {…}
    

    This basically would give you store.filters.filters

    You also have incorrect cast to RootState, the root state is a type of store it’s not a type of slice state

    So

    const departureTimeRange = useSelector((store: RootState) => store.filters.filters.departureTimeRange);
    

    Should work as expected

    P.s.: you should remove :RootState from initialState, then you should remove key filters from initialState and it should work as expected (with your current useSelector)