0

I'm having trouble determining if my component hierarchy really needs getDerivedStateFromProps, if the cases where it is needed is really as rare as the documentation makes it sound. It might be a fundamental misunderstanding about React/Redux design.

class AttributeList extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      attributes: props.attributes,
      newAttributes: []
    }
  }

  addNewAttribute = () => {
      // add new empty attribute to newAttributes state
  }

  onKeyChange = () => {
      // update appropriate attribute key
  }

  onValueChange = () => {
      // update appropriate attribute value
  }

  saveAttributes = () => {
      // save the, API call
  }

  render = () => {
      this.state.attributes.map((pair) => {
          <Attribute
            //pass data + functions, functional component />
      })
      this.state.newAttributes.map((pair) => {
          <Attribute
            //pass data + functions, functional component />
      })
  }

  static getDerivedStateFromProps(){
      // ?? do comparisons here to choose to remove or keep certain newAttributes? or just ignore result of save and keep interface as-is, just show error message if saving failed. 
  } 
}

I have a parent component AttributeList which renders a bunch of Attributes, which are essentially key-value pairs. AttributeList receives the list of attributes of a document as props. However, the attributes can be edited, so it initializes its state (this.state.attributes) with this.props.attributes. Normally keys are immutable, but if a user adds a new attribute to the list, he can edit both the key and value. At any point, a user can save all the attributes. When the new attributes are saved, I'd like to disabled editing the keys for them as well. Here is the dilemma.

Option one is to save the document and just hope it worked, and then clear the new attributes list and mark all the attributes as saved (disabling the key input). I think this would be the "fully uncontrolled" solution, where once the state is initialized the component deals with everything on it's own. However, what if the save fails? I don't want to show and incorrect state to the user.

So I want to do option two. After save, fetch the document, which will load the attribute list and re-render the component. However I need to get rid of my new attributes since they are now a part of the attributes prop. I would like to verify that the new attributes are actually a part of the attributes prop now. It seems like this would happen ingetDerivedStateFromProps where I would on each render cycle check if any new attribute keys already exist in the attributes prop, and remove them from the "new" list if they do, and return that state.

But is this really the right time to use getDerivedStateFromProps? It seems to me that for any page that a user is "editing" something where you make an API call to save it, if you want to render based on the saved data ("the truth"), then I need to use getDerivedStateFromProps. Or perhaps from a design perspective it is better to show a message akin to "data not successfully saved" and keep the state as is, to prevent any data loss. I'm honestly not sure.

minifigmaster125
  • 165
  • 3
  • 12
  • If you want advice for when to use `getDerivedStateFromProps` I would recommend to read the official React docs - https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html If you plan is to sync the state from props on successfully data save change, then the docs says this is an antipattern. If you can I would recommend to do a fully controlled component. If you can't re-design, then yes you can use `getDerivedStateFromProps` to achieve what you want, where you update your local state from props if data was successfully saved. Should be your only last option IMHO. – Kunukn Dec 10 '18 at 07:46
  • https://stackoverflow.com/questions/53340767/is-it-a-good-practice-to-use-getderivedstatefromprops-to-map-props-to-the-data-s/53342015#53342015 Have a look at this one. – Pranay Tripathi Dec 10 '18 at 11:48

1 Answers1

0

I don't see how getDerivedStateFromProps comes into it as there's no reason you need to copy props into state is there? When an old attribute value is changed you save it to the redux store, when new attribute properties are changed you can update local state (or save them to a different slice of the store, or differentiate them some other way). Update rules can be enforced in the update handlers or during merge on save.

// dispatch redux action to update store
onOldValueChange = () => {}

// this.setState to update new value
onNewKeyChange = () => {}
onNewValueChange = () => {}

render = () => {
  this.props.attributes.map((pair) => {
    <Attribute
      //pass data + onOldValueChange, functional component />
  })
  this.state.newAttributes.map((pair) => {
    <NewAttribute
      //pass data + functions, functional component />
  })
}
lecstor
  • 5,619
  • 21
  • 27
  • But what about when a newAttribute is saved? Is it idiomatic to fetch the document that was just updated, and if so, it's likely that the attributes prop now contains one of the newAttributes that was just saved, and thus I should be removing that newAttribute from the state. – minifigmaster125 Dec 15 '18 at 18:09
  • yes, you'd remove the newAttributes from state once they're saved. – lecstor Dec 15 '18 at 21:42
  • What would that look like? On save, dispatch action to fetch document again. Document is fetched, new attributes prop is passed down, and then if the new attributes is different from the old attributes (in componentDidUpdate), setState as needed? – minifigmaster125 Dec 16 '18 at 00:14
  • hmm.. I think I'd be inclined to do an optimistic update, ie update the store with values from state, then save to server. Depending on your api you'd either be saving to contents of the store or the content of state so when you clear the state would come down to when works for your app and how you'd handle a save failure. Request tracking in state or store could be used to not render the state properties while they exist in both state and store (props). – lecstor Dec 16 '18 at 03:42