0

I am Reactjs beginner and just started working on an existing Reactjs project that uses react-recompose module.

I am trying to declare a property and initialize it using withProps. The property initialization will use few other existing properties. I am passing this property to few child classes and these child classes will modify this property multiple times by calling handlers from parent.
In the end, user will click on 'save' and the property state will be sent to server.
What is actually happening is after child classes call parent handlers which modify this property the withProps is getting invoked sometimes in between which reinitializes the property to it's initial state; Which results in recent changes to property being lost. Strangely, withProps isn't getting called every time the property is modified but only sometimes unpredictably.

I would like to know how can I define a property which is initialized as a product of few other properties; and which is initialized only once when the page is loaded.

Please find sample code below.

const mapStateToProps = state  => ({
  user: state.users.user,
  allUsers: state.users.allUsers  
}); 



export function getRecentUsers(user, allUsers) {
    //Based on some criteria return some of the users from allUsers
    return recentUsers; 
}

export const Container = compose(
  connect(mapStateToProps, mapDispatchToProps),
  withProps(({ user, allUsers, recentUsers}) => {
    return {
        recentUsers: getRecentUsers(user, allUsers)
    };
  }), 
  withHandlers({
    modifyRecentUsers: ({ recentUsers }) => (someUsers, myThis) => {
      //Modify recentUsers here
      myThis.setState({recentUsers : recentUsers});
    },
  ...
  ...
}(Users);

export const Users = ({
  user,
  allUsers,
  recentUsers,
  modifyRecentUsers
  }) => (
  <Child
    user={user}
    allUsers={allUsers}
    myThis={user.myThis}
    recentUsers={recentUsers}
    modifyRecentUsers={modifyRecentUsers}            
  />
 );

export class Child extends Component {
  constructor(props) {
    super(props);
    this.user=this.props.user;
    this.allUsers=this.props.allUsers;
    this.myThis=this.props.myThis;
    this.recentUsers=this.props.recentUsers;
    this.modifyRecentUsers=this.props.modifyRecentUsers;    
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.recentUsers != undefined) {
      this.recentUsers = nextProps.recentUsers;
      this.setState({        
        recentUsers: nextProps.recentUsers
      });
    }
  }

  updateRecentUsers() {
    this.modifyRecentUsers(someUsers);
  }

     render() {
        return (
            //some html
        );
     }
 }

EDIT

In the example code I posted recentUsers is a property derived from user and allUsers and declared and initialized using withProps. user and allUsers are part of redux store.
Even if either user or allUsers property changes I don't want recentUsers to be re-computed once it was initialized in withProps. Because, after initialization in withProps, I am updating recentUsers in response to application user actions, and any re-computation of it wipes out all these changes. Is it possible to initialize it only once?
Also, changes to user or allUsers are only local. These changes are not written to the redux store until user clicks on 'Save'. Inside withHandlers I am doing something like user.name = 'some name'. I hope until these changes are written to redux store the user or allUsers updates should not result in re-initialization of recentUsers in withProps.

Ancient
  • 1
  • 1

1 Answers1

0

withProps gives you readonly props that you generally compute from something. Your call to myThis.setState does not update that object. It's creating a key with the same name in your component's state.

With redux, state mutations belong to the reducers.

If recentUsers can be computed from users and allUsers and both are in redux, then your withProps is fine. It is your your modifyRecentUsers that is wrong. It should dispatch a modifyUser action. You reducer will then update the state (users and/or allUsers) and your component will re-render. That will trigger your withProps again, which will recompute recentUsers from users and allUsers.

Sylvain
  • 19,099
  • 23
  • 96
  • 145
  • Thanks for the reply @Sylvain. Based on your comments I have added additional details to my post under 'Edit' section. – Ancient Apr 05 '18 at 10:49
  • And by mistake edited your post earlier instead of editing my question. Unable to undo it now -( – Ancient Apr 05 '18 at 10:50