stent icon indicating copy to clipboard operation
stent copied to clipboard

React component does not re-render if state remains and a prop change

Open vladejs opened this issue 5 years ago • 5 comments

Hello.

I'm working on an electrón app that manage folders.

I want that, when the user drops some folders into the app, let's say five, a message shows indicating which folder is being processed.

The way I'm doing it is by not changing the state at all but just sending the same array of folders (these are just objects) with the difference that the current folder has a prop named current set to true, and it gets toggled to every folder being processed.

So, the problem is that, only by passing to the machine a slightly different array, it doesn't re-render the component, and it only do that if I change the state and change it back.

Any hint in how to solve this?

vladejs avatar Jan 21 '19 05:01 vladejs

Would you be able to show a code example?

thekarel avatar Jan 21 '19 09:01 thekarel

Well, there is an action that gets an array of files and has to return the same array of files, but continuously update the array before it finishes:

const withSize = (state, files) => {
  
   const newFiles = processFiles(files, currentBeingProcessed => {
  const ufiles = files.map(f => {
      return { 
          ...f, 
          current: f.path === currentBeingProcessed
      }
  })
  this.processingFiles(ufiles)
})
}  

this.processingFiles changes the state. On the UI, I have a list of the files and put a label on the one being processed.

The label should be seen on every file, but it only shows on the first item, and when the process finishes, the UI remains intact.

The UI should reflect the current file being processed

vladejs avatar Jan 21 '19 15:01 vladejs

If this is still an issue, could you provide more context?

Is processingFiles able to move the machine into a new state, i.e. is the transition valid?

thekarel avatar Jan 29 '19 09:01 thekarel

First of all, apologies @thekarel for late reply.

Answering your question, processingFiles moves the machine from INITIAL, to PROCESSING the first time the callback is called.

When the callback is called again, the same PROCESSING state is called but with a different version of the data, meaning, the machine remains in its current state, but stent should notice that the data changed, and update the view. That's my issue, the view never re-renders.

I know it's because I don't move to another state the second time the callback is called, but the data actually changed.

So I'm wondering how to achieve this task.

In order to provide more context, the use case I'm tacking here is to analyze a list of folders and provide the user feedback in which folder is being processed.

vladejs avatar Feb 15 '19 18:02 vladejs

If your change is buried in your props, and therefore doesn't show a difference between your props and nextProps, you may need to use shouldComponentUpdate.

shouldComponentUpdate(nextProps, nextState) {
  if ( this.props.item.liked !== nextProps.item.liked ) {
    return true
  }
  return false
}

I don't suggest doing a direct comparison of nested properties that may or may not exist like this. It's better to have a helper function that returns null if the property doesn't exist. I.e.

maybeNull(this.props, ['item', 'liked'])

sunwukonga avatar May 29 '19 04:05 sunwukonga