Can I use index of map function as key for my React components containing dynamic unpredictable text?

huangapple go评论76阅读模式
英文:

Can I use index of map function as key for my React components containing dynamic unpredictable text?

问题

以下是翻译好的部分:

我有这段代码,我正在将动态文本解析为单独的行,并为每行文本渲染单独的组件。

我使用map函数创建一个元素数组,React要求列表中的每个元素都具有唯一的键

我知道通常不建议使用index作为键。但在这种情况下,我还能做什么呢?

问题

在这种情况下,我能否使用index作为元素的key,而不会出现问题?可能会出现什么问题?

注意1:我不能使用值作为键,因为所有行可能具有完全相同的值,因此它们将不是唯一的。

注意2:此代码在博客文章的管理表单中运行。我编写一些自定义标记文本,就像在StackOverflow问题文本区域中一样,我需要解析它以在屏幕上呈现为博客文章时为其添加适当的样式。例如:**粗体文本**等。并且每行应该呈现为不同的段落。

更新

我已经阅读了您在评论和答案中提到的文章。作者指出了以下内容:


Can I use index of map function as key for my React components containing dynamic unpredictable text?

我的情况是否满足这3个要求?

1 - 它们是否会更改?从理论上讲,它们会更改。

2 - 它们没有ID。

3 - 它们肯定没有被过滤。但它们是否被重新排序?如果您复制“line1\nline2\nline3”并粘贴到记事本中,然后将其更改为“line3\nline2\nline1”并将其粘贴回textarea中,是否算作重新排序?我刚刚测试了一下,它呈现得很好。

无论如何,到目前为止,我还没有遇到任何问题,感觉可以安全使用。但我想要深入解释它在这种情况下是如何工作的。

function App() {
  const [inputValue, setInputValue] = React.useState("line1\nline2\nline3");
  const lineItems = inputValue.split("\n").map((line, index) => 
    <TextLine 
      key={index}
      index={index}
      value={line}
    />
  );
  
  return(
    <React.Fragment>
      <textarea 
        onChange={(event) => setInputValue(event.target.value)} 
        value={inputValue}
        style={{width: "300px", height: "60px"}}
      />
      {lineItems}
    </React.Fragment>
  );
}

function TextLine(props) {
  return(
    <div>{props.value + " (key = " + props.index + ")"}</div>
  );
}

ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

<details>
<summary>英文:</summary>

I got this code where I&#39;m parsing dynamic text into separate lines and rendering individual components for each line of text. 

I&#39;m using the `map` function to create an array for the elements and **React demands a unique key for each element on the list**.

I know usually it&#39;s not ideal to use `index` as the key. But in this case, what else can I do?

**QUESTION**

Can I use `index` as the `key` for the elements in this case without having issues? What could go wrong?

**Note1**: I cannot use the values as the keys, because all lines might have the exact same values, hence they wouldn&#39;t be unique.

**Note2**: This code runs inside an Admin form for BlogPosts. I write some custom markup text, just like in the textarea for questions on StackOverflow and I need to parse it to give it proper styles when rendered out on the screen as a blog post. Like: `**bold text**`, etc. And each line should be rendered as a different paragraph.

**UPDATE:**

I&#39;ve read the article you all mentioned in comments and answer. And here&#39;s what the author points out:

---

[![enter image description here][1]][1]

Does my case meet all 3 requirements?

1 - Do they change? In theory they do. 

2 - They have no ids.

3 - They are not filtered for sure. But are they reordered? What if you copy `&quot;line1\nline2\nline3&quot;` paste into Notepad and change it to `&quot;line3\nline2\nline1&quot;` and paste it back into the `textarea`. Does it count as re-ordering? I just tested it and it renders just fine.

Anyway, so far I haven&#39;t run into any issues and it feels safe to use. But I would like an in-depth explanation of how it works in this case.

---


&lt;!-- begin snippet: js hide: false console: true babel: true --&gt;

&lt;!-- language: lang-js --&gt;

    function App() {
      const [inputValue,setInputValue] = React.useState(&quot;line1\nline2\nline3&quot;);
      const lineItems = inputValue.split(&quot;\n&quot;).map((line,index) =&gt; 
        &lt;TextLine 
          key={index}
          index={index}
          value={line}
        /&gt;
      );
      
      return(
        &lt;React.Fragment&gt;
          &lt;textarea 
            onChange={()=&gt;setInputValue(event.target.value)} 
            value={inputValue}
            style={{width: &quot;300px&quot;, height: &quot;60px&quot;}}
          /&gt;
          {lineItems}
        &lt;/React.Fragment&gt;
      );
    }

    function TextLine(props) {
      return(
        &lt;div&gt;{props.value + &quot; (key = &quot; + props.index + &quot;)&quot;}&lt;/div&gt;
      );
    }

    ReactDOM.render(&lt;App/&gt;, document.getElementById(&quot;root&quot;));

&lt;!-- language: lang-html --&gt;

    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;
    &lt;div id=&quot;root&quot;/&gt;

&lt;!-- end snippet --&gt;


  [1]: https://i.stack.imgur.com/J95le.png

</details>


# 答案1
**得分**: 4

以下是已翻译的部分:

**Note**: 如果项目具有唯一的 ID(且非原始列表),请不要使用索引,因为根据文档,这是一种反模式。

当项目没有唯一的 ID 时,您可以使用索引。

```javascript
const Numbers = ['One', 'Two', 'Three', 'Four'];

const App = () => (
  <ul>
    {Numbers.map(
      (number, index) => <li key={index}>{number}</li>
    )}
  </ul>
)

没有唯一键时,React 无法区分元素是被移除还是仅内容发生了更改。

唯一键的解决方案...

1- 您可以创建一个生成唯一键/ID/数字/字符串的函数,并使用它。

2- 您可以使用 npm 包(库),如 uuiduniqidshortid...

3- 我建议使用从数据库获取的唯一 ID,如果您有的话。

英文:

Note: Don't use the index if the items have a unique id (and a non-primitives list should), because it's an anti-pattern as per documentation

When you don't have a unique id for the items, you can use the index.

const Numbers = [&#39;One&#39;, &#39;Two&#39;, &#39;Three&#39;, &#39;Four&#39;];

const App = () =&gt; (
  &lt;ul&gt;
  {Numbers.map (
    (number, index) =&gt; &lt;li key={index}&gt;{number}&lt;/li&gt;
  )}
  &lt;/ul&gt;
)

Without a unique key, React couldn’t differentiate if the element was removed or just the content is changed.

Solutions for unique key...

1- You can create a function to generate unique keys/ids/numbers/strings and use that

2- You can use npm packages(library) like uuid, uniqid, shortid...

3- I recommend using the unique ID you get from the database, If you get it.

huangapple
  • 本文由 发表于 2020年1月3日 17:22:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/59575917.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定