1

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.

Vincent Rye
  • 422
  • 1
  • 4
  • 13
  • pure redux? dispatch new action with event payload ... reducers ... updated state ... connected components are updated - no other magic (handshake?) needed? – xadm May 18 '19 at 14:08
  • Yeah, that's exactly what I wanted to avoid. I'm not interested in that whole routine, you see this react-big-calendar applies dnd and nice features like that, having to update react store everytime on each drag and drop is going to be slow (i believe) even if I hash the array, which I already did. – Vincent Rye May 18 '19 at 14:14

2 Answers2

1

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.

xadm
  • 8,219
  • 3
  • 14
  • 25
  • That's actually a much smoother way to go about it. What's the gain of componentDidUpdate over getDrivedStateFromProps? They both get called on each render, no? – Vincent Rye May 18 '19 at 15:03
  • `getDrivedStateFromProps` doesn't have access to prev props, you shoud store time in state to compare – xadm May 18 '19 at 15:20
0

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
}
Bruno Portis
  • 151
  • 2
  • 11
  • Besides the fact that it doesn't really answer the question, how is that any different from my current merge? It works similar to setState() where you can return one key/value pair and it will merge it into state. Correct not? – Vincent Rye May 18 '19 at 14:12