我正在创建一个React应用,并且具有以下列表:
const list = [
{
id: '1',
task: 'task 1',
activities: [{
'Google': [
{url: 'https://www.google.com'},
{visited: false}
],
'Yahoo': [
{url: 'https://www.yahoo.com'},
{visited: false}
],
'Bing': [
{url: 'https://www.bing.com'},
{visited: false}
]
}],
visitedAll: false
},
{
id: '2',
task: 'task 2',
activities: [{
'Facebook': [
{url: 'https://www.facebook.com'},
{visited: false}
],
'Instagram': [
{url: 'https://www.instagram.com'},
{visited: false}
],
'Twitter': [
{url: 'https://www.twitter.com'},
{visited: false}
]
}],
visitedAll: false
}
];
我正在遍历列表,如下所示:
<ul>
{list.map(item => (
<li key={item.id}>
{item.task}
<ul>
{Object.keys(item.activities[0]).map((act, i) => <li key={i}>{act}</li>)}
</ul>
</li>
))}
</ul>
这将产生以下输出:
visited
键设置为true
?答案 0 :(得分:0)
您可以先使用activities
方法将reduce
属性修改为一个对象,然后为每个带有visited
属性的状态子项目创建单独的组件。
const {useState} = React;
const list = [{"id":"1","task":"task 1","activities":[{"Google":[{"url":"https://www.google.com"},{"visited":false}],"Yahoo":[{"url":"https://www.yahoo.com"},{"visited":false}],"Bing":[{"url":"https://www.bing.com"},{"visited":false}]}],"visitedAll":false},{"id":"2","task":"task 2","activities":[{"Facebook":[{"url":"https://www.facebook.com"},{"visited":false}],"Instagram":[{"url":"https://www.instagram.com"},{"visited":false}],"Twitter":[{"url":"https://www.twitter.com"},{"visited":false}]}],"visitedAll":false}]
.map(({activities, ...rest}) => ({
...rest, activities: activities.reduce((r, e) => Object.assign(r, e), {})
}))
const SubListItem = props => {
const {data, name} = props;
const [visited, setVisited] = useState(data[1].visited);
const toggle = event => {
event.preventDefault();
setVisited(!visited);
}
return <li>
<a style={{color: visited ? "green" : ''}}
onClick={toggle}
href={data[0].url}>{name}</a>
</li>
}
const List = ({data}) => <ul>
{data.map(item => <li key={item.id}>
<a href="">{item.task}</a>
<ul>{Object.keys(item.activities).map(act => (
<SubListItem key={act} name={act} data={item.activities[act]} />
))}</ul>
</li>)}
</ul>
ReactDOM.render(<List data={list} />, document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="app"></div>
答案 1 :(得分:0)
我将实现一个Anchor
组件,该组件将保存visited
的状态。
此外,父组件App
的状态为“所有访问的锚”。
const list = [
{
id: '1',
task: 'task 1',
activities: {
Google: {
url: 'https://www.google.com'
},
Yahoo: {
url: 'https://www.yahoo.com'
},
Bing: {
url: 'https://www.bing.com'
}
}
},
{
id: '2',
task: 'task 2',
activities: {
Facebook: {
url: 'https://www.facebook.com'
},
Instagram: {
url: 'https://www.instagram.com'
},
Twitter: {
url: 'https://www.twitter.com'
}
}
}
];
const Anchor = ({ name, href, onClick }) => {
const [isVisited, setIsVisited] = useState(false);
const onAnchorClick = () => {
setIsVisited(visited => !visited);
onClick();
};
return (
// v add href={href}
<a onClick={onAnchorClick}>{`${name} is ${
isVisited ? '' : 'not'
} visited`}</a>
);
};
// You can get such object from reducing the list
const visitedInitial = {
Google: false,
Yahoo: false,
Bing: false,
Facebook: false,
Instagram: false,
Twitter: false
};
const App = () => {
const [visited, setVisited] = useState(visitedInitial);
return (
<>
<h1>
{Object.values(visited).every(value => value === true)
? 'All Visited'
: 'Please visit all'}
</h1>
<ul>
{list.map(({ id, task, activities }) => (
<li key={id}>
{task}
<ul>
{Object.entries(activities).map(([name, { url }], i) => (
<li key={i}>
<Anchor
name={name}
href={url}
target="_blank"
onClick={() =>
setVisited(prev => ({ ...prev, [name]: true }))
}
/>
</li>
))}
</ul>
</li>
))}
</ul>
</>
);
};
答案 2 :(得分:0)
这是根据您提供的项目提供的答案。我已经将绘图子项目提取到一个接受项目参数的单独函数中。每个子项目都有一个onClick
处理程序,该处理程序将visited
设置为true
。
import React, { useState, useCallback } from "react";
import ReactDOM from "react-dom";
const initialItems = [
{
id: "1",
task: "task 1",
activities: [
{
Google: [{ url: "https://www.google.com" }, { visited: false }],
Yahoo: [{ url: "https://www.yahoo.com" }, { visited: false }],
Bing: [{ url: "https://www.bing.com" }, { visited: false }]
}
]
},
{
id: "2",
task: "task 2",
activities: [
{
Facebook: [{ url: "https://www.facebook.com" }, { visited: false }],
Instagram: [{ url: "https://www.instagram.com" }, { visited: false }],
Twitter: [{ url: "https://www.twitter.com" }, { visited: false }]
}
]
}
];
function App() {
const [items, setItems] = useState(initialItems);
const setVisited = React.useCallback(
(id, activityName) => {
const item = items.find(item => item.id === id);
if (item) {
item.activities[0][activityName][1].visited = true;
setItems([...items]);
}
},
[items, setItems]
);
const getSubItems = useCallback(
item => {
const activities = item.activities[0];
return Object.keys(activities).map(activityName => {
const url = activities[activityName][0].url;
const onClick = () => {
setVisited(item.id, activityName);
};
return (
<li key={activityName}>
<a
href={url}
onClick={onClick}
target="_blank"
rel="noopener noreferrer"
>
{activityName}
</a>
</li>
);
});
},
[setVisited]
);
return (
<div>
<ul>
{items.map(item => (
<li key={item.id}>
{item.task}
<ul>{getSubItems(item)}</ul>
</li>
))}
</ul>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);