Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useSelector is not updating the state in reduxjs/toolkit

I am trying to update the state.user.price state to some other value using reduxjs/toolkit but it is not working properly. I know this has to do with immutablity then I tried returning new objects without changing them but it didn't work.

const initialUserState = {
  isLoggedIn: !!localStorage.getItem("token"),
  carName: "",
  price: "any",
  avaliablity: "any",
  type: "any"
}

const userSlice = createSlice({
  name: "user",
  initialState: initialUserState,
  reducers: {
    handleAuthState: state => {
      state.isLoggedIn = !!localStorage.getItem("token");
    },
    changeCarName: (state, action) => {
      state.carName = action.payload;
    },
    changeAvailablity: (state, action) => {
      state.avaliablity = action.payload;
    },
    changeType: (state, action) => {
      state.type = action.payload;
    },
    changePrice: (state, action) => {
      state.price = action.payload;
    }
  }
});
const store = configureStore({
  reducer: {
    UI: UISlice.reducer,
    user: userSlice.reducer,
    car: carSlice.reducer
  }
});

export default store;
export const userActions = userSlice.actions;
const Filters = () => {
  const type = useSelector(state => state.user.type);
  const price = useSelector(state => state.user.price);
  const carName = useSelector(state => state.user.carName);
  const availablity = useSelector(state => state.user.availablity);

  const sendRequest = async () => {
    console.log("priceInSendRequestFunction = ", price);
  }

  const priceHandler = event => {
    if (event.target.value === "") {
      dispatch(userActions.changePrice("any"))
    } else {
      console.log("event.target.value = ", event.target.value);
      dispatch(userActions.changePrice(event.target.value));
    }
    sendRequest();
  }
  return (
    <Select onChange={priceHandler} placeholder="Select Price">
      <option value="2000">Below 2000</option>
      <option value="4000">2000 - 4000</option>
      <option value="6000">4000 - 6000</option>
      <option value="infinity">Above 6000</option>
      <option value="any">Any</option>
    </Select>
  )
}

The value of price in sendRequest function should get the updated value but it is getting another value.

like image 565
Daniel Vanum Avatar asked Feb 02 '26 11:02

Daniel Vanum


1 Answers

The current selected price state is closed over in callback scope when priceHandler is called. priceHandler dispatches an action to the store and immediately calls sendRequest. The component has yet to rerender and access any updated Redux state values.

You can forward the value to sendRequest that you are updating the state to:

const sendRequest = async (price) => {
  console.log("priceInSendRequestFunction = ", price);
};

const priceHandler = event => {
  const { value } = event.target;
  const newPrice = value || "any";

  console.log({ newPrice });
  dispatch(userActions.changePrice(newPrice));

  sendRequest(newPrice);
};

Or you can import the store and access the current state directly:

import store from '../path/to/store';

...

const sendRequest = async () => {
  const state = store.getState();
  const { price } = state.user;

  console.log("priceInSendRequestFunction = ", price);
};

const priceHandler = event => {
  const { value } = event.target;
  const newPrice = value || "any";

  console.log({ newPrice });
  dispatch(userActions.changePrice(newPrice));

  sendRequest();
};

If the sendRequest function/logic is effectively a "side-effect" then an alternative might be to convert the changePrice action into an asynchronous action, e.g. a Thunk.

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

const initialUserState = {
  isLoggedIn: !!localStorage.getItem("token"),
  carName: "",
  price: "any",
  avaliablity: "any",
  type: "any"
};

export const changePrice = createAsyncThunk(
  "user/changePrice",
  async (price, thunkAPI) => {
    console.log("price in changePrice action = ", price);
    try {
      // side-effect to send price ...somewhere
      ...
      return price;
    } catch(error) {
      return thunkAPI.rejectWithValue(error);
    }
  }
);

const userSlice = createSlice({
  name: "user",
  initialState: initialUserState,
  reducers: {
    handleAuthState: state => {
      state.isLoggedIn = !!localStorage.getItem("token");
    },
    changeCarName: (state, action) => {
      state.carName = action.payload;
    },
    changeAvailablity: (state, action) => {
      state.avaliablity = action.payload;
    },
    changeType: (state, action) => {
      state.type = action.payload;
    },
  },
  extraReducers: builder => {
    builder
      // Update local price state if side-effect successful
      .addCase(changePrice.fulfilled, (state, action) => {
        state.price = action.payload;
      });
  },
});
const Filters = () => {
  const dispatch = useDispatch();

  const {
    availablity,
    carName,
    price,
    type,
  } = useSelector(state => state.user);

  const priceHandler = event => {
    const { value } = event.target;
    const newPrice = value || "any";

    console.log({ newPrice });
    dispatch(userActions.changePrice(newPrice));
  }

  return (
    <Select onChange={priceHandler} placeholder="Select Price">
      <option value="2000">Below 2000</option>
      <option value="4000">2000 - 4000</option>
      <option value="6000">4000 - 6000</option>
      <option value="infinity">Above 6000</option>
      <option value="any">Any</option>
    </Select>
  )
}
like image 121
Drew Reese Avatar answered Feb 05 '26 00:02

Drew Reese



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!