Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Suggestion: createSlice to export selectors #2658

Closed
Harris-Miller opened this issue Aug 30, 2022 · 2 comments
Closed

Feature Suggestion: createSlice to export selectors #2658

Harris-Miller opened this issue Aug 30, 2022 · 2 comments

Comments

@Harris-Miller
Copy link

@reduxjs/toolkit has done an amazing job abstracting common functionality to reduce boiler plate. One thing that I feel is missing is that createSlice does not produce base selectors for the root keys of a reducer

So I would like to add selectors to the return object of createSlice

{
    name : string,
    reducer : ReducerFunction,
    actions : Record<string, ActionCreator>,
    caseReducers: Record<string, CaseReducer>.
    getInitialState: () => State,
    selectors: Record<string, Selector> // new!
}

selectors has a key matching each key of initialState that is passed to createSlice. The idea is to simply allow us to reuse a pre-generated selector function the same way actions are generated

// user.slice.ts
type UserState = {
  email: string;
}

const initialState: UserState = {
  email: ''
};

export const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    setEmail: (state, action: PayloadAction<string>) => {
      state.email = action.payload;
    }
  }
});

// UserInfo.tsx
import { userSlice } from '../user.slice';

const UserInfo = () => {
  const dispatch = useDispatch();
  // we should use selectors generated right from the slice
  const email = useSelector(userSlice.selectors.email);
  
  const onChange = (e) => {
    // the same way we use actions!
    dispatch(userSlice.actions.setEmail(e.currentTarget.value);
  };

  return (
    <input onChange={onChange} value={email} />
  );
}

The intention of these pre-generated selectors is simply to cover the most common use case of a reducer, one with a flat object where you just want to get the value of each key. No more, no less.

This addition would be incredibly simple to add with very little overhead and provides additional reduction of boilerplate. And while it would not always be used for more complex reducers, I don't feel there would be much harm or overhead to including them regardless

Alternative to always including them:

  • opt-in to their generation by passing createSlice({ selectors: true });
  • granularly select which keys get generated createSlice({ selectors: ['email'] });, where selectors: (keyof State)[]
@EskiMojo14
Copy link
Collaborator

EskiMojo14 commented Aug 30, 2022

see #193 and #91 - it used to do this but was removed for reasons stated in the issue discussion (#91)

edit: looks like it was simplified to a single "select my slice" selector, then removed

@markerikson
Copy link
Collaborator

markerikson commented Aug 30, 2022

Yep. We actually discourage having selectors for every single field in a slice. Additionally, there's no point in generating memoized selectors for each field:

https://redux.js.org/usage/deriving-data-selectors#balance-selector-usage

and this really isn't something I want to add.

Another issue is that these selectors wouldn't know anything about the root state type, which is what a typical selector expects as its first argument. We could hypothetically do something like the entityAdapter.getSelectors(selectTheRightPieceOfData) approach, but at that point there really isn't much benefit over just writing a couple of functions yourself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants