0

Consider this

  componentDidMount() {
    const { currentUserId, userList } = this.props; 
    //I get these from redux' mapStateToProps function; 
    //these are not passed down as regular props.

    Mousetrap.bind(['shift+right'], () =>
      nextUser(currentUserId, userList)
    );
  }

Say I have 10 users in my list, and we start with user 1. When I start the app, it will go from user 1 to user 2; However, it won't go any further since the value of currentUserId will eternally be user 1.

How can I circumvent this and have the arguments be dynamic, so that the arguments will be updated?

Edit: currentUserId & userList are passed on to the Component via Redux

R. Kohlisch
  • 2,823
  • 6
  • 29
  • 59

2 Answers2

0

If you want things to be dynamic, consider copying the currentUserId to the state in the constructor and adjusting the state as needed with this.setState({currentUserId: }) Example:

constructor(props) {
  super(props);
  this.state = { currentUserId: props.currentUserId };
}

componentDidMount() {
  const { userList } = this.props;
  const { currentUserId } = this.state;

  Mousetrap.bind(['shift+right'], () =>
    nextUser(currentUserId, userList)
  );

}

I don't know how your nextUser function works but it if it returns the next userId, you could do:

Mousetrap.bind(['shift+right'], () =>
  this.setState({currentUserId:nextUser(currentUserId, userList)});
);

in the componentDidMount().

mikat
  • 1
  • 1
  • 2
0

If you need to update the function, after the component is mounted, you need to use componentDidUpdate to react to prop changes during the life of a component.

componentDidMount will be called once (when the component became visible) and your function will be set to the current prop => onClick will select the second user.

After that, your props change (currentUserId will now be the second user), but you don't update your function. That is why it will be stuck on the second user.

To achieve what you intend to do, use componentDidUpdate in combination with componentDidMount like this:

componentDidUpdate(prevProps) {
    const { currentUserId, userList } = this.props;
    if(prevProps.currentUserId !== currentUserId || prevProps.userList !== userList ) {
        Mousetrap.bind(['shift+right'], () =>
          nextUser(currentUserId, userList)
        );
    }
}

As an alternative, you could also remove the parameters from nextUser and let the action/reducer handle the update by setting the currentUserId within the reducer directly.

Hope this helps. Happy coding.

Domino987
  • 8,475
  • 2
  • 15
  • 38
  • `As an alternative, you could also remove the parameters from nextUser and let the action/reducer handle the update by setting the currentUserId within the reducer directly.` - I wanted to do just that, but it seems to be an anti pattern? I've asked the question here https://stackoverflow.com/questions/57376470/anti-pattern-accessing-state-in-reducer-how-to-handle-interdependent-reducers but haven't received a proper answer. One comment says actions should be pure - but I didn't know that, was only aware that reducers had to be. – R. Kohlisch Aug 07 '19 at 13:51
  • Yes action should be pure but every rule should be taken with a grain of salt and in my opinion, this is one use-case, where you could do it within the reducer. But I am sure there are people disagreeing with me. If you strictly want to keep the action pure, use the componentDidUpdate approach. If you want to keep it hassle free and easier to maintain, use the reducer approach. – Domino987 Aug 07 '19 at 13:56