redux-views icon indicating copy to clipboard operation
redux-views copied to clipboard

Best practice to reuse parametric selectors in arrays

Open martinkutter opened this issue 4 years ago • 1 comments

What is the best practice (if it is possible) to reuse the getCarView selector in the following example?

reduxStore = {
    defaultFront: "defaultFront.jpg",
    defaultBack: "defaultBack.jpg",
    view: "front",
    favorits: ["uid1", "uid2"],
    cars: {
        "uid1": {
            front: "front.jpg",
            back: "back.jpg",
        },
        "uid2": {},
        ...
    }
}

const getUidFromProps = createIdSelector(props => props.uid);
const getView = state => state.view;
const getCars = state => state.cars;
const getDefaultBack = state => state.defaultBack;
const getDefaultFront = state => state.defaultFront;
const getFavorits = state => state.favorits;

const getCar = createSelector(
    [getUidFromProps, getCars],
    (uid, cars) => cars[uid]
);

const getCustomCarFront = createSelector([getCar], car => car.front);
const getCustomCarBack = createSelector([getCar], car => car.back);

const getCustomCarView = createSelector(
    [getCustomCarFront, getCustomCarBack, getView],
    (front, back, view) => view === "front" ? front : back
);
const getDefaultCarView = createSelector(
    [getDefaultBack, getDefaultFront, getView],
    (front, back, view) => view === "front" ? front : back
);
const getCarView = createSelector(
    [getCustomCarView, getDefaultCarView],
    (customView, defaultView) => customView || defaultView
);

const getViewsOfFavoritCars = createSelector(
    [getFavorits], 
    (favorits) => favorits.map(uid => {
        // reuse "getCarView" with given "uid"
    })
);

Thanks in advance

martinkutter avatar May 20 '21 11:05 martinkutter

After rethinking about this situation with a colleague, it is the same as described in #28. Unfortunately without good caching...

reduxStore = {
    defaultFront: "defaultFront.jpg",
    defaultBack: "defaultBack.jpg",
    view: "front",
    favorits: ["uid1", "uid2"],
    cars: {
        "uid1": {
            front: "front.jpg",
            back: "back.jpg",
        },
        "uid2": {},
        ...
    }
}

const identity = x => x;
const getUidFromProps = createIdSelector(props => props.uid);
const getView = state => state.view;
const getCars = state => state.cars;
const getDefaultBack = state => state.defaultBack;
const getDefaultFront = state => state.defaultFront;
const getFavorits = state => state.favorits;

const getCar = createSelector(
    [getUidFromProps, getCars],
    (uid, cars) => cars[uid]
);

const getCustomCarFront = createSelector([getCar], car => car.front);
const getCustomCarBack = createSelector([getCar], car => car.back);

const getCustomCarView = createSelector(
    [getCustomCarFront, getCustomCarBack, getView],
    (front, back, view) => view === "front" ? front : back
);
const getDefaultCarView = createSelector(
    [getDefaultBack, getDefaultFront, getView],
    (front, back, view) => view === "front" ? front : back
);
const getCarView = createSelector(
    [getCustomCarView, getDefaultCarView],
    (customView, defaultView) => customView || defaultView
);

const getViewsOfFavoritCars = createSelector(
    [identity, getFavorits], 
    (state, favorits) => favorits.map(uid => getCarView(state, { uid })
);

Or is there any better solution?

martinkutter avatar May 21 '21 10:05 martinkutter