I am currently working on calendar component using react-big-calendar.

I currently have one Wrapper for it that pulls data from an database and sends it into the Calendar Component. However, I am making a feature that one can 'send' calendar events to that component from anywhere.

Currently I have only have use cases, which is from the website's built in notification system, there will be a feature to add an external event sent over as a notification to your own calendar. I might however want to push events to users calendars from another webapplication through my socket server (socket.io).

I am not sure what is the "proper" way to go about it in react, technically.

How I went about it now is that I added

 static getDerivedStateFromProps(nextProps, prevState){
    if(nextProps.propInput === true){
        nextProps.reset()
        return {events : {...prevState.events, ...nextProps.events}}
    } else return null
}

inside my CalendarWrapper, which basically does the following for me: 1) I update the props sent into the wrapper, either from parent component or from the redux store (i will be using the 2nd) 2) This triggers getDrivedStateFromProps and checks if it receives propInput as true, and if that's the case, it merges the new events being sent down as props into the current events of the calendar. 3) it then runs a callback function (nextProps.reset()), to reset propInput to FALSE, which triggers another run of getDrivedStateFromProps, but this time returns null and doesn't cause a new setState.

This was my own dreamed up solution on HOW to push new events to this calendar wrapper from the redux store. It seems unorthodox, but for me it's the only way to have a middle ground with pure redux and everything saved in redux, and having local state of each component.

Is there a technically better and more perfomant way to go about solving this problem?

Thanks in advance.

2 Answers

0
bsap On

You have to return a merge of your prevState with your new state, like this:

static getDerivedStateFromProps(nextProps, prevState){
if(nextProps.propInput === true){
    nextProps.reset()

    return {...prevState, ...{ 
               events : nextProps.events
           }
    }
} else return null
}
1
xadm On

I would save a timestamp (instead boolean propInput) with new events sent to redux. Comparing 'last update time' is enough to take a decision of update - no need to clear propInput flag (no reset() call ... reducers... etc.).

You don't even need to store this timestamp in state - no need to use getDerivedStateFromProps ("fired on every render, regardless of the cause") - classic solution:

componentDidUpdate(prevProps) {
  if (this.props.newEventsTime !== prevProps.newEventsTime) {
    setState({events : {...this.state.events, ...this.props.newEvents}})
  }
}

More optimal should be

shouldComponentUpdate(nextProps, nextState) {
  if (nextProps.newEventsTime !== this.props.newEventsTime) {
    setState({events : {...this.state.events, ...this.props.newEvents}});
    return false; // no render needed in this pass
  }
  return (nextState.events === this.state.events) ? false : true;
}

- update on events object ref change.