You should be doing it like that for performance reasons:
const user = useSelector(state => state.userReducer);
Your selector will be run whenever an action is dispatched. If it returns something different then on the last run it will force the component to re-render. By spreading into a new object it will always return a new object. Therefore your component will re-render on every action that gets dispatched.
From the react-redux docs:
useSelector() will also subscribe to the Redux store, and run your
selector whenever an action is dispatched.
[...]
When an action is dispatched, useSelector() will do a reference
comparison of the previous selector result value and the current
result value. If they are different, the component will be forced to
re-render.
[...]
useSelector() uses strict === reference equality checks by default, not shallow equality
Also I find the key userReducer to be a little awkward. It is just the user not the reducer of the user. A reducer is a pure function that turns actions into changes not an object of data.
EDIT:
As noted by @Adam in the comment if you want to further reduce the amount of re-renders you can use a memorized selector to select only the state you are interested in. A good library to create such a selector is reselect.
// example
import { createSelector } from 'reselect';
const basicUserDataSelector = createSelector(
({user}) => user.id,
({user}) => user.name,
({user}) => user.lastName,
(id, name, lastName) => ({id, name, lastName})
);
// usage
const user = useSelector(basicUserDataSelector);
In your case the easiest way to only select the state needed ist to tell useSelector to do a shallow equal comparison instead of a reference equality comparison. useSelector accepts a comparator function as the second argument:
import { shallowEqual, useSelector } from 'react-redux'
const user = useSelector(
({user}) => ({
id: user.id
name: user.name
lastName: user.lastName
}),
shallowEqual
);
It is best practice to only take as few data as needed to render from the store to limit the amount of re-rendering. The extra cost of selecting more data then actually needed depends on the component and the frequency of changes on the selected data.