beek
beek

Reputation: 3750

Update React when Data in Object in Store has changed

I've found lots of similar problems, can't seem to sort my case

I have a component that won't re-render when data changes.

When MODE changes, which is a string, the entity re-renders and updates.

When hotspot.description changes, it won't update.

I can see the description has changed in the store, I can console log the changes all the way to this component.

However I just can't get this component to update when the description changes in hotspot.

Any clues!?

Connected

const mapStateToProps = (state) => {
  return {
    mode: state.admin.hotspot.mode,
    hotspot: state.admin.hotspot.edit,
  }
}

Pure

export default class HotspotRenderer extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      hotspot:props.hotspot,
      mode:props.mode,
    }
  }

  componentWillReceiveProps(nextProps) {
    this.setState({
      hotspot : nextProps.hotspot,
      mode: nextProps.mode,
    })
  }

  render() {
    const {hotspot,mode} = this.state

    const isEditingText = hotspot && mode === HOTSPOT_EDIT_MODE.TEXT
    const html = hotspot != null ? ReactHtmlParser(draftToHtml(hotspot.description)) : null

    return (
      <div>
        {
          isEditingText &&
          <Container>
            <div className={`hotspot-renderer hotspot${hotspot.id} hotspot-text-default`}><div>{html}</div></div>
          </Container>
        }
      </div>
    )
  }
}

admin.state.hotspot

const initialState = {
  isDraggingNewHotspot: false,
  edit:null,
  mode:null,
}

export function hotspot(prevState=initialState, action) {
  switch(action.type) {
  case START_ADD_HOTSPOT:      return { ...prevState, isDraggingNewHotspot: true }
  case FINISH_ADD_HOTSPOT:     return { ...prevState, isDraggingNewHotspot: false }
  case ADD_HOTSPOT:            return { ...prevState,  mode: HOTSPOT_EDIT_MODE.DRAG}
  case EDIT_HOTSPOT:           return { ...prevState,  edit: action.hotspot}
  case FINISH_EDIT_HOTSPOT:    return { ...prevState,  edit: null}
  case EDIT_HOTSPOT_MODE:      return { ...prevState, mode: action.mode }
  case UPDATE_HOTSPOT:         return { ...prevState, edit : action.hotspot }
  case GO_TO_EDIT_SCENE:       return { ...prevState, edit :null,mode :null }
  case UPDATE_SCENE_HOTSPOT_SUCCESS: return { ...prevState, edit: processUpdatedHotspot(prevState.edit,action.payload) }
  default:                     return prevState
  }
}

function processUpdatedHotspot(prev,update){

  if(!prev)
    return null

  if(!prev.id)
    prev.id = update.id

  return prev
}

Here is where the description is edited

  updateHotspotDescription(description){
    let hotspot = this.state.hotspot
    hotspot.description = description
    hotspot.imageUpdateRequired = true
    this.setState({hotspot : hotspot})
    this.state.onUpdateHotspot(hotspot)
  }

This is dispatched whenever text is changed, via a draft-js editor.

The state is updated with the changes, and another entity is aware of them.

Upvotes: 0

Views: 140

Answers (2)

Dyo
Dyo

Reputation: 4464

You have to follow the Immutable pattern to update your value, even before passing it to redux (see updating nesting objects in the link).

So before sending hotspot.edit to your reducer be sure to update the nested description object following the immutable pattern like this :

updateHotspotDescription(description){
    const hotspot = { 
        ...this.state.hotspot,
        description, // shorthand for description: description
        imageUpdateRequired: true,
    };
    this.setState({ hotspot });
    this.state.onUpdateHotspot(hotspot);
}

Upvotes: 2

Jose Paredes
Jose Paredes

Reputation: 4080

So you have to question yourself, are you sure your action it's being actually taken?

Any non-case in the switch statement will return the previous state, therefore It's normal that It won't re-render.

Some tips to follow to verify if your redux state it's being updated:

  • Make sure your constants are imported correctly in your actions and in your reducer
  • Make sure the triggered action it's being properly taken by the reducer
  • Log the next state in your reducer before your return it, so you can be sure that the next state is the correct one

Follow this steps and let me know if your problem persists

Upvotes: 0

Related Questions