使用 React 对 json/array 使用 .map() 函数的问题



我正在构建一个 React-App,我在json/array.map()-function工作时遇到了问题。 我的服务器端 json 对象看起来像:

let jsonlist = [
{
Title: "first title",
Listofitems: ["Item 01", "Item 02", "Item 03"]
},
{
Title: "second title",
Listofitems: ["Item 04", "Item 05", "Item 06"]
}
]

我的代码客户端示例如下所示:

const [lists, setmylist] = useState([]);
const fetchFact = () => {
fetch("http://myapi:4000/getmyList")
.then((response) => response.json())
.then((data) => setmylist(data));
}
useEffect(() => {
fetchFact()
}, []);
return (
<div className='container'>
{lists.map(singleobject => {
var test = Object.entries(singleobject);
{ console.log(test) }
{ console.log(test[0][0]) }
<p>{test[0][0]}</p>
})}
</div>
);

如果我运行这个,我会得到{ console.log(test)}

[
[
"Title",
"first title"
],
[
"Listofitems",
[
"Item 01",
"Item 02",
"Item 03"
]
]
]

但是<p>{test[0][0]}</p>不会显示。如果我改变

{lists.map(singleobject => {})}

到类似的东西

{projects.map(singleproject => (
<p key={hereineedauniqueid}>Just checkin</p>    
))}

Just checkin就像我想要的那样显示 2 次,但我不知道如何从json/array中获取我的值。我是否需要更改json/array的结构或需要更改代码?

我想我需要使用{lists.map(singleobject => {})}函数,因为我想为json/array中的每个 elment 创建一个表和一个react-bootstrap/Modal,并希望在每个特定模态中显示json/array的值

感谢您的帮助

在此回调中,您将普通的 JavaScript 语法与 JSX 语法混合在一起:

.map(singleobject => {
var test = Object.entries(singleobject);
{ console.log(test) }
{ console.log(test[0][0]) }
<p>{test[0][0]}</p>
})}

在 JSX 中,当将表达式插入到 React 组件中时(或在调试时,对于副作用),{ expression }的语法很有用。但是你不是在JSX的上下文中 - 你在一个普通的JavaScript函数中。您的{}表示普通块

{ console.log(test) }

就像做

if (true) {
console.log(test)
}

然后,如果你在 JSX 中,把

<p>{test[0][0]}</p>

就在内插日志旁边可以工作 - 但同样,您不在 JSX 中。您需要返回<p>才能看到结果。但是,如果要显示值包含的内容并循环访问每个条目,请考虑对对象的条目返回.map,而不是这样做。

const App = () => {
const lists = [
{
Title: "first title",
Listofitems: ["Item 01", "Item 02", "Item 03"]
},
{
Title: "second title",
Listofitems: ["Item 04", "Item 05", "Item 06"]
}
];
return (
<div className='container'>
{lists.map(singleobject => Object.entries(singleobject)
.map(([key, value]) => (
<div>
<div>Key: {key}</div>
<div>Value is a: {typeof value}</div>
</div>
))
)}
</div>
);
};
ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>

但是,由于每个对象的键相同,因此循环访问条目似乎是多余的。直接引用.TitleListofitems会更容易。

const App = () => {
const lists = [
{
Title: "first title",
Listofitems: ["Item 01", "Item 02", "Item 03"]
},
{
Title: "second title",
Listofitems: ["Item 04", "Item 05", "Item 06"]
}
];
return (
<div className='container'>
{lists.map(singleobject => (
<div>
<div>{singleobject.Title}</div>
<div>{singleobject.Listofitems.join(', ')}</div>
</div>
))}
</div>
);
};
ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>

我认为没有必要在每个对象上使用Object.entries。我会将它们保留为对象,并使用它们的key/value对将东西渲染到 DOM。

例如,对于您的jsonlist

let jsonlist = [
{
Title: "first title",
Listofitems: ["Item 01", "Item 02", "Item 03"]
},
{
Title: "second title",
Listofitems: ["Item 04", "Item 05", "Item 06"]
}
]

您可以像这样简单地渲染第一个对象:

return (
<div className='container'>
{lists.map(singleobject => {
return (
<div>
<h3>{singleobject.Title}</h3>
<ol>
{singleobject.Listofitems.map(item => {
return <li>{item}</li>
})
</ol>
</div>
)
})}
</div>

如果要为列表中的每个对象构建组件,则可以将信息作为 props 传递给lists.map(singleobject => {})函数中的组件。

就这样做

return (<p>{test[0][0]}</p>);

你只需要知道箭头函数的基础知识

如果将接口分解为较小的组件,则可能更容易考虑问题。您知道data是您必须map的对象数组,但您的listofitems也是一个数组,因此您也会map这些对象是有道理的。

因此,在容器中map从端点获取的数据,为每个对象生成一个新列表(带有标题和进一步的项目列表)。为此,您可以使用单独的List组件,将当前迭代的对象传递到该组件中。(你在问题中提到你想要一个表格,但由于我不知道你想要的表格的格式,所以列表更容易生成 - 但原则仍然成立。将ListListItem替换为表行组件和表单元格组件)。

List组件中,您可以为标题创建一个元素和一个列表元素,然后在该元素中 - 使用ListItem组件映射对象的项目列表。

请注意,通过这样做,您需要将key属性添加到您正在迭代的元素中(否则 React 会给您一个警告)。因此,考虑到这一点,此示例重构数据以为每个对象提供id,并且还为每个项目创建具有自己的 id 的对象。

例如:

[{ id: 1, title: 'first title', items: [{ id: 1-1, value: 'Item 01' }...]

const data=[{title:"first title",items:["Item 01","Item 02","Item 03"]},{title:"second title",items:["Item 04","Item 05","Item 06"]}];
// Create an updated dataset with ids
const updated = data.map((obj, id) => {
obj.id = id + 1;
obj.items = obj.items.map((item, id) => {
return { id: `${obj.id}-${id + 1}`, value: item };
});
return obj;
});
// For this example passing in the data to
// the component rather than fetching it
// `map` over the array and, for each obj create
// a list with the List component
function Example({ data }) {
return (
<div className="container">
{data.map(obj => {
return <List key={obj.id} obj={obj} />
})}
</div>
);
}
// The List component accepts an object, and 
// we can destructure the title, and items, from
// the object. We create a title, and a list element
// and then `map` again over the items array to create
// a set of list items with the ListItem component
function List({ obj }) {
const { title, items } = obj;
return (
<div className="list">
<div className="title">{title}</div>
<ul>
{items.map(item => {
const { id, value } = item;
return <ListItem key={item.id} item={value} />
})}
</ul>
</div>
);
}
// Accepts an item, and returns
// a list item element
function ListItem({ item }) {
return <li>{item}</li>;
}
ReactDOM.render(
<Example data={updated} />,
document.getElementById('react')
);
.title { text-transform: uppercase; }
ul { list-style: none; margin-left: 0px; padding: 0px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

最新更新