Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
161 views
in Technique[技术] by (71.8m points)

Pass a whole object to redux reselect selector, but change it only if one property of the object changes

Started working with Reselect and there's one thing I can't seem to find an answer for.

Say I have a helper fn (getVehicleList) which does some heavy calculations, so I don't want it to re-run too much. I use state selectors to get the properties I need, something like:

const getVehicles = (state) => state.vehicles.vehicles;
const getVehicle = (state) => state.vehicles.vehicle;
const getUserId = (state) => state.auth.user.id;

I then have implemented the createSelector:

const getVehicles = createSelector(
  [getVehicles,
   getVehicle,
   getUserId],
  (vehicles, vehicle, id) => getVehicleList(
    vehicles,
    vehicle,
    id,
  ),
);

Now, vehicle returns an object with multiple fields. If any of these fields change, the object changes and so everything is recomputed again. Is there a way to stop this recomputing until the id and only the id of the vehicle changes?

I tried doing a state selector for the id, like

const getVehicle = (state) => state.vehicles.vehicle.id;

But that doesn't work for me, cause I need the whole vehicle object inside my helper fn and not just the id.

Thanks in advance for the help!

question from:https://stackoverflow.com/questions/65953109/pass-a-whole-object-to-redux-reselect-selector-but-change-it-only-if-one-proper

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can try the following:

const getVehicles = (state) => state.vehicles.vehicles;
const getVehicle = (state) => state.vehicles.vehicle;
const getUserId = (state) => state.auth.user.id;
const selectVhicleId = createSelector(
  [getVehicle],
  ({ id }) => id //return only the id
);
const selectVehicles = createSelector(
  [getVehicles, selectVhicleId, getUserId],
  (vehicles, vehicleId, id) =>
    getVehicleList(vehicles, { id: vehicleId }, id)
);

Here is some information about how I use reselect with React.

Here is an example that re calculate vehicles when vehicle.id changes (or any of the other dependencies). It will not re calculate if other values of vehicle change so the vehicle used getVehicleList gets a stale vehicle passed to it that is only refreshed when vehicle.id changes:

const getVehicles = (state) => state.vehicles.vehicles;
const getVehicle = (state) => state.vehicles.vehicle;
const getUserId = (state) => state.auth.user.id;
const createSelectVehicles = (vehicle) =>
  createSelector([getVehicles, getUserId], (vehicles, id) =>
    getVehicleList(vehicles, vehicle, id)
  );

const Component = () => {
  //only re calculate vehicle if vehicle.id changes
  const vehicle = useSelector(
    getVehicle,
    (a, b) => a?.id === b?.id
  );
  //only create the selector when vehicle changes
  //  vehicle only changes when vehicle.id changes
  const selectVehicles = React.useMemo(
    () => createSelectVehicles(vehicle),
    [vehicle]
  );
  //vehicles is re calculated when vehicle.id changes
  //  or when state.vehicles.vehicles changes or
  //  when state.auth.user.id changes
  const vehicles = useSelector(selectVehicles);
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...