React JSX 在迭代对象时出现错误。

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

React JSX error while iterating over object

问题

I have a JS object myFieldsObj as below;

{
field1: {value: 1},
field2: {value: 2},
field3: {value: 3}
}

In my JSX, I want to iterate over this and render some output.

<MyCustomDialog>
{
  <>
  {Object.keys(myFieldsObj).map((key, index) => (
      <div key={index}>
          <Field field={myFieldsObj[key]} />
      </div>
  ))}
  </>
}
</MyCustomDialog>

However the above is giving an error saying

Uncaught ReferenceError: index is not defined

Not sure what the issue is with the syntax.

英文:

I have a JS object myFieldsObj as below;

{
	field1: {value: 1},
	field2: {value: 2},
	field3: {value: 3}
}

In my JSX, I want to iterate over this and render some output.

&lt;MyCustomDialog&gt;
{
&lt;&gt;
Object.keys(myFieldsObj).map((key, index) =&gt; {
    &lt;div key={index}&gt;
        &lt;Field field={myFieldsObj[key]} /&gt;
    &lt;/div&gt;
})
&lt;/&gt;
}
&lt;/MyCustomDialog&gt;

However the above is giving an error saying

> Uncaught ReferenceError: index is not defined

Not sure what the issue is with the syntax.

答案1

得分: 1

以下是翻译的内容:

  1. 由于您正在尝试在另一个自定义组件(MyCustomDialog)中创建Field组件,您需要让MyCustomDialog渲染这些children。您可以通过确保从其props访问children并在(语义化的)元素内返回它来实现。注意:在此将子元素包装在呈现元素中意味着您可以在其他组件中不使用React片段(<></>)。

  2. 确保在map内部返回每个Field组件。您正在使用花括号,因此需要显式的return。也没有真正需要单独的div包装器。只需将键应用于字段组件即可。

  3. 您可能会发现使用数组而不是对象更容易处理数据。请注意,数组中的对象都具有id属性,您可以将其值用作map迭代中的键,而不是通常应避免使用的map的索引。

在这个示例中,在迭代中,我将每个完整的对象作为data传递给props,以便在Field组件中同时访问namevalue

如果您需要更多信息,请告诉我。

英文:

To try and tie TJ's and Jon's comments up in a working example with some additional commentary.

  1. Since you're trying create Field components within another bespoke component (MyCustomDialog) you'll need to have MyCustomDialog render those children. You can do that by ensuring that children is accessed from its props and returned inside a (semantic) element (here: section). Note: wrapping the child elements in a presentation element here means you can do away with the React fragment (&lt;&gt;) in your other component.

  2. Make sure that you return each Field component within the map. You're using curly braces so an explicit return is required. There's also no real need for that separate div wrapper. Just apply the key to the field component instead.

(More after the first example...)

<!-- begin snippet: js hide: false console: true babel: true -->

<!-- language: lang-js -->

const { useState } = React;

// MyCustomDialog needs to be able to
// render its child elements. Since we wrap them
// in a section element we can do without the
// React fragment in the Example component
function MyCustomDialog({ children }) {
  return &lt;section&gt;{children}&lt;/section&gt;;
}

// Basic field component
function Field({ field }) {
  return &lt;div&gt;{field.value}&lt;/div&gt;;
}

// Passing in the data to the component, and
// iterating over it. On each iteration a new
// field component it created with a new field object
function Example({ myFieldsObj }) {
  return (
    &lt;MyCustomDialog&gt;
      {Object.keys(myFieldsObj).map((key, index) =&gt; {
        return &lt;Field key={index} field={myFieldsObj[key]} /&gt;
      })}
    &lt;/MyCustomDialog&gt;  
  );
}

const myFieldsObj = {
  field1: { value: 1 },
  field2: { value: 2 },
  field3: { value: 3 }
};

const node = document.getElementById(&#39;root&#39;);
const root = ReactDOM.createRoot(node);
root.render(&lt;Example myFieldsObj={myFieldsObj} /&gt;);

<!-- language: lang-html -->

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

<!-- end snippet -->

  1. You may find it easier using an array for your data instead of an object. Note here the objects in the array all have an id property the value of which you can use for the key in the map iteration instead of map's own index which you should generally avoid.

    In this example, in the iteration, I'm adding the each complete object as data in the props so I can access both the name and the value in the Field component.

<!-- begin snippet: js hide: false console: true babel: true -->

<!-- language: lang-js -->

const { useState } = React;

// MyCustomDialog needs to be able to
// render its child elements. Since we wrap them
// in a section element we can do without the
// React fragment in the Example component
function MyCustomDialog({ children }) {
  return &lt;section&gt;{children}&lt;/section&gt;;
}

// Basic field component
function Field({ data }) {
  return (
    &lt;div&gt;
      &lt;h4&gt;{data.name}&lt;/h4&gt;
      &lt;p&gt;{data.value}&lt;/p&gt;
    &lt;/div&gt;
  );
}

// Passing in the data to the component, and
// iterating over it. On each iteration a new
// field component it created with a new field object
function Example({ myFields }) {
  return (
    &lt;MyCustomDialog&gt;
      {myFields.map(obj =&gt; {
        return (
          &lt;Field
            key={obj.id}
            data={obj}
          /&gt;
        );
      })}
    &lt;/MyCustomDialog&gt;  
  );
}

const myFields = [
  { id: 1, name: &#39;field1&#39;, value: 1 },
  { id: 2, name: &#39;field2&#39;, value: 2 },
  { id: 3, name: &#39;field3&#39;, value: 3 }
];

const node = document.getElementById(&#39;root&#39;);
const root = ReactDOM.createRoot(node);
root.render(&lt;Example myFields={myFields} /&gt;);

<!-- language: lang-html -->

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

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月15日 00:32:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76248574.html
匿名

发表评论

匿名网友

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

确定