Can I manipulate values within mapStateToProps

I'm learning React and Redux and found following problem that I can't get my head around, I have a config object in store that may looks like this:

{
    general:{duration:100,strength:100},
    gameA:{strength:50},
    gameB:{duration:50}
}

Where general object will always be there and will have all properties, and it could have one or more game objects with all or part of overriding properties.

Now, games GameA and GameB are using duration and strength props so I can do:

const mapStateToProps = (state) => {
    return {
        duration: state.general.duration,
        strength: state.general.strength
}
export default connect(mapStateToProps)(GameA);

but as my store example shows I could have different setup per game type which I want then override general setup. Can I then do this manipulation in the mapStateToProps function?

const mapStateToProps = (state) => {
    let {duration, strength} = state.general;
    if(state.gameA && state.gameA.duration) duration = state.gameA.duration;
    if(state.gameA && state.gameA.strength) strength= state.gameA.strength;
    return {
        duration: duration,
        strength: strength
}

Upvotes: 3

Views: 725

Answers (1)

random-forest-cat
random-forest-cat

Reputation: 35984

Another pattern is to use reselect to compute derived values from state:

https://redux.js.org/docs/recipes/ComputingDerivedData.html#composing-selectors

Selectors offer the benefit of memoizing derived values which proves extremely useful given the sensitivity of react lifecycle methods (why make this calculation more than once if you don't have to?).

I find they are super useful for abstracting presentation logic from a component.

Here is a short and very simple example:

const mapStateToProps = state => ({
  price: getPriceWithDollarSign(state), 
})

// selectors/price.js
const getProduct = (state) => state.product // returns { price: 7.00 }

// i find it useful to immediately identify selectors with `get` so I know its a selector
export const getPriceWithDollarSign = createSelector(getProduct, (item) => {
  // this will only be evaluated once for this specific item, future calls to this method
  // will return the value cached by re-select (until the methods input changes)
  return `$${item.price}` // item is value returned by getProduct
})

In your component, you'd end up with this.props.price -> '$7.00'

The beauty of reselect is in its ability to compose multiple selectors, making it easy to share and use other selectors within one another.

Check out https://github.com/reactjs/reselect for more information.

While usage of reselect is geared towards deriving values from redux state, you can use the library with any data structure / library / framework you please.

Upvotes: 3

Related Questions