如何在JSX中使用map嵌套循环?

vma*_*uet 16 javascript jsx reactjs

我无法实现两个嵌套map:

render() {
    return (
      <table className="table">
        <tbody>
          {Object.keys(this.state.templates).map(function(template_name) {
            return (
              <tr key={template_name}><td><b>Template: {template_name}</b></td></tr>

              {this.state.templates[template_name].items.map(function(item) {
                return (
                  <tr key={item.id}><td>{item.id}</td></tr>
                )
              })}
            )
          })}
        </tbody>
      </table>
    )
  }
Run Code Online (Sandbox Code Playgroud)

这给了一个SyntaxError: unknown: Unexpected token.

你如何map在JSX中嵌套调用?

Sag*_*b.g 29

你需要将它包装在一个元素中.

像这样的东西(tr由于表元素的规则,我添加了额外的东西):

  render() {
    return (
      <table className="table">
        <tbody>
          {Object.keys(templates).map(function (template_name) {
            return (
              <tr key={template_name}>
                <tr>
                  <td>
                    <b>Template: {template_name}</b>
                  </td>
                </tr>
                {templates[template_name].items.map(function (item) {
                  return (
                    <tr key={item.id}>
                      <td>{item}</td>
                    </tr>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
      </table>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

运行示例(没有表):

const templates = {
  template1: {
    items: [1, 2]
  },
  template2: {
    items: [2, 3, 4]
  },
};

const App = () => (
  <div>
    {
      Object.keys(templates).map(template_name => {
        return (
          <div>
            <div>{template_name}</div>
            {
              templates[template_name].items.map(item => {
                return(<div>{item}</div>)
              })
            }
          </div>
        )
      })
    }
  </div>
);
ReactDOM.render(<App />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)

  • 是的,使用元素来包装东西使它工作.虽然,我没有完全使用你的解决方案,因为嵌套的`<tr>`无效,根据http://validator.w3.org/nu/.相反,我用`<tbody>`包装了一些东西,并且在一个表中有几个`<tbody>`是有效的HTML(例如:/sf/answers/215375331/).还是非常感谢. (2认同)
  • 这里的关键是使用 2 个 `return` 语句 (2认同)

ade*_*hox 9

我不确定它在技术上是否正确,但作为助记符,可以记住:“每个返回的 JSX 元素必须只有一个 JSX 元素”。

因此,大多数时候,只需将您拥有的内容包装成一<></>对(或任何其他任意标签对)即可解决问题。例如,如果您<div>从组件的 render 方法返回两个 s,那将是不正确的,但是,如果您将这两个包装成一对<></>,则很可能它会被修复。

但请注意,有时它可能会变得更加模糊,例如,当彼此嵌套两个 ES6 映射时,例如:

<tbody>
{
  this.categorizedData.map(
    (catgGroup) => (
      <tr>
        <td>{catgGroup}</td>
      </tr>
      this.categorizedData[catgGroup].map(
        (item) => (
          <tr>
            <td>{item.name}</td>
            <td>{item.price}</td>
          </tr>
        )
      )
    )
  )
}
</tbody>
Run Code Online (Sandbox Code Playgroud)

可以这样修复:

<tbody>
{
  this.categorizedData.map(
    (catgGroup) => (
      <> // <--- Notice this, it will wrap all JSX elements below in one single JSX element.
        <tr>
          <td>{catgGroup}</td>
        </tr>
        {this.categorizedData[catgGroup].map( // <--- Also notice here, we have wrapped it in curly braces, because it is an "expression" inside JSX.
          (item) => (
            <tr>
              <td>{item.name}</td>
              <td>{item.price}</td>
            </tr>
          )
        )}
      </>
    )
  )
}
</tbody>
Run Code Online (Sandbox Code Playgroud)

PS:(来自文档):您还可以从 React 组件返回元素数组:

render() {
  // No need to wrap list items in an extra element!
  return [
    // Don't forget the keys :slight_smile:
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}
Run Code Online (Sandbox Code Playgroud)