S
S
sharkdest2019-01-24 12:51:44
JavaScript
sharkdest, 2019-01-24 12:51:44

How to replace the .map() function in my case?

Hello, the problem is this:
I am using react-csv in a React application:

...
render() {
 return (
 ...
 {rows.map(row => (
                <CSVLink
                  key={row.number}
                  className="btn btn-secondary btn-download"
                  data={rows}
                  separator={";"}
                  filename="netpositions.csv"
                >
                  <span className="oi oi-data-transfer-download" />
                </CSVLink>
 ))}
...
 )
}

Without key={row.number} - an empty file is saved, it was advised to add a key.
And everything works well, if not:
5c498a7a9a6a6116161541.png
How many rows in the table - so many buttons and there will be (one button is needed), it's not strange, because I use .map().
Another plus to everything:
5c498a9fde187845166712.png
How can I solve the problem in a normal way?
Thanks in advance.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Askhat Bikmetov, 2019-01-24
@sharkdest

The question was answered by the author of the question, I, in turn, will try to explain what happened.
Rendering in react always follows the least laborious path, namely, it calculates the delta (difference) between the new state and the previous one, if any. For example:

class TodoList extends React.Component {
  state = {
    todos: [
      'Commit',
      'Push'
    ]
  }
  render() {
    return <ul>
      {this.state.todos.map(item => {
        return <li>{ todo }</li>
      }
    </ul>
  }
}

If the state of the component changes, say by adding an element to the front of the todos list, so it becomes like this:
const todos = [
  'Init',
  'Commit',
  'Push'
]

React will compute two VirtualDOM trees:
// Начальный стейт
<ul>
  <li>Commit</li>
  <li>Push</li>
</ul>
// Добавлен элемент
<ul>
  <li>Init</li> // <- разница начинается здесь и до конца древа
  <li>Commit</li>
  <li>Push</li>
</ul>

There is work being done here that could have been avoided. For example, if the element were added to the end of the list:
const todos = [
  'Commit',
  'Push',
  'Merge'
]

Then the react would get the other two element trees for comparison:
// Начальный стейт
<ul>
  <li>Commit</li>
  <li>Push</li>
</ul>
// Добавлен элемент
<ul>
  <li>Commit</li>
  <li>Push</li>
  <li>Merge</li> <- разница начинается здесь, от начала и до сих по ничего не менялось
</ul>

The delta of these two lists is smaller, which means that less work needs to be done.
It is quite obvious that <li>Commit</li>they <li>Push</li>did not change, but react is not smart enough to understand this. To help him, you should use a special prop key={}. It can be a value of any type, the only requirement is that the value must stably identify the corresponding data.
If the component looked like this:
class TodoList extends React.Component {
  state = {
    todos: [
      { id: 0, text: 'Commit' },
      { id: 1, text: 'Push' }
    ]
  }
  render() {
    return <ul>
      {this.state.todos.map(item => {
        return <li key={todo.id}>{ todo.text }</li>
      }
    </ul>
  }
}

That adding an element to the beginning of the array would generate the following state:
const todos = [
  { id: 2, text: 'Init' },
  { id: 0, text: 'Commit' },
  { id: 1, text: 'Push' }
]

And, again, two element trees:
// Начальный стейт
<ul>
  <li>Commit</li> // id 0
  <li>Push</li> // id 1
</ul>
// Добавлен элемент
<ul>
  <li>Init</li> // id 2 новый элемент отобразится в начале
  <li>Commit</li> // id 0
  <li>Push</li> // id 1 
</ul>

Thanks to the hint, React will not take into account in the delta elements whose IDs have not changed, and, as a result, will not do unnecessary actions.
Thus, using an index in an array as a key is not a good idea, especially if the array will change. For the same reason, it should not be used Math.random()as a key, as you are almost guaranteed to always get unstable ids.
You can read more about this here - Reconciliation.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question