3

I have this button and playing around withStateHandlers from recompose. The goal is just to change button state from active: false to active: true.

const EnhancedButton = withStateHandlers(
  ({ initialState = false }) => ({
    active: initialState
  }),
  {
    onTrigger: ({ active }) => ({
      active: true
    })
  }
)(({ active, onTrigger, children, id }) => {
  console.log(active)
  return (
    <Button
      onClick={() => onTrigger()}
      toggle
      active={active}
      size="massive"
      style={styles.button}
      as={Link}
      to={`/${id}`}
    >
      {children}
    </Button>
  )
})

I click on the button, then I get redirected to new page, then I go back and the button is still active: false where I expect it to be active: true

karolis2017
  • 2,195
  • 8
  • 24
  • 49

1 Answers1

5

The docs for withStateHandlers specify:

withStateHandlers(
  initialState: Object | (props: Object) => any,
  stateUpdaters: {
    [key: string]: (state:Object, props:Object) => (...payload: any[]) => Object
  }
)

Which means that each state-updater property is a function that gets state and props arguments and returns another function, which in turn takes the optional payload arguments (i.e. whatever you pass as arguments when you call onTrigger) and returns the new state.

Your onTrigger returns the new state instead of a function, so the type is incorrect. If you wrap the result in an arrow function, it should work:

onTrigger: ({ active }) => () => ({
  active: true
})
Oblosys
  • 14,468
  • 3
  • 30
  • 38
  • Thanks for your response, but it's still the same thing. I console.log(active) and it's always false when I come back to the component. Maybe I get pushed to a new location before the state is set to active: true? – karolis2017 Jul 14 '18 at 04:29
  • When I push to a new route I'm rendering a new component and the previous one is gone from the DOM. So when I get back to it it rerenders and has an initial state which is `false`. Does this makes sense or not? – karolis2017 Jul 14 '18 at 05:10
  • 2
    You'll need the extra `() =>` to get it to work at all, but yes, if a component is unmounted and later remounted, its state gets initialized again. If you want to prevent that, you'll need to keep the state in an ancestor component that stays mounted, or use a state management library like redux. – Oblosys Jul 14 '18 at 14:10