我正在构建一个 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>
但是,由于每个对象的键相同,因此循环访问条目似乎是多余的。直接引用.Title
和Listofitems
会更容易。
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
组件,将当前迭代的对象传递到该组件中。(你在问题中提到你想要一个表格,但由于我不知道你想要的表格的格式,所以列表更容易生成 - 但原则仍然成立。将List
和ListItem
替换为表行组件和表单元格组件)。
在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>