React Material UI 多重折叠
Posted
技术标签:
【中文标题】React Material UI 多重折叠【英文标题】:React Material UI Multiple Collapse 【发布时间】:2019-02-06 01:25:09 【问题描述】:目前我的列表都已折叠,但它们链接到“打开”的一种状态,因此如果我打开一个列表,则所有其他列表都会打开。 在每个列表没有很多状态的情况下,将折叠彼此分开的最佳方法是什么。
编辑:应用程序正在无限循环
App.tsx
interface IState
error: any,
intro: any,
threads: any[],
title: any,
export default class App extends React.Component<, IState>
constructor (props : any)
super (props);
this.state =
error: "",
intro: "Welcome to RedQuick",
threads: [],
title: ""
;
this.getRedditPost = this.getRedditPost.bind(this)
this.handleClick = this.handleClick.bind(this)
public getRedditPost = async (e : any) =>
e.preventDefault();
const subreddit = e.target.elements.subreddit.value;
const redditAPI = await fetch('https://www.reddit.com/r/'+ subreddit +'.json');
const data = await redditAPI.json();
console.log(data);
if (data.kind)
this.setState(
error: undefined,
intro: undefined,
threads: data.data.children,
title: data.data.children[0].data.subreddit.toUpperCase()
);
else
this.setState(
error: "Please enter a valid subreddit name",
intro: undefined,
threads: [],
title: undefined
);
public handleClick = (index : any) =>
this.setState( [index]: true );
public render()
return (
<div>
<Header
getRedditPost=this.getRedditPost
/>
<p className="app__intro">this.state.intro</p>
this.state.error === "" && this.state.title.length > 0 ?
<LinearProgress />:
<ThreadList
error=this.state.error
handleClick=this.handleClick
threads=this.state.threads
title=this.state.title
/>
</div>
);
Threadlist.tsx
<div className="threadlist__subreddit_threadlist">
<List>
props.threads.map((thread : any, index : any) =>
<div key=index className="threadlist__subreddit_thread">
<Divider />
<ListItem button=true onClick=props.handleClick(index)/* component="a" href=thread.data.url*/ >
<ListItemText primary=thread.data.title secondary=<p><b>Author: </b>thread.data.author</p> />
props[index] ? <ExpandLess /> : <ExpandMore />
</ListItem>
<Collapse in=props[index] timeout="auto" unmountOnExit=true>
<p>POOP</p>
</Collapse>
<Divider />
</div>
)
</List>
</div>
【问题讨论】:
这真的很模糊,但是您可以对列表进行集成并将其中一个传递给打开状态 对不起,我已经编辑了这个问题,所以它更容易理解 我已经添加了一个可能的解决方案的答案。动态打开状态 【参考方案1】:你必须为每次折叠创建一个不同的状态,我建议动态使用 setState 和你从 map 函数获得的索引,你可能必须将索引参数传递给 handleClick 函数并根据它更改状态
<div className="threadlist__subreddit_threadlist">
<List>
props.threads.map((thread : any, index : any) =>
<div key=index className="threadlist__subreddit_thread">
<Divider />
<ListItem button=true onClick=props.handleClick(index)/* component="a" href=thread.data.url*/ >
<ListItemText primary=thread.data.title secondary=<p><b>Author: </b>thread.data.author</p> />
props[index] ? <ExpandLess /> : <ExpandMore />
</ListItem>
<Collapse in=props[index] timeout="auto" unmountOnExit=true>
<p>POOP</p>
</Collapse>
<Divider />
</div>
)
</List>
</div>
您的 handleClick 应如下所示:
public handleClick = (index : any) =>
this.setState( [index]: true );
【讨论】:
更改 handleClick 函数时,出现错误“错误 TS1005: ':' expected.”在 openArray[index] 部分。也不是最好使用 prevState 让折叠在打开后关闭吗?但是我在使用 prevState 时也会收到错误 是的,你可以用 prevState 做到这一点,我给你的是一个小例子而不是完整的答案,我编辑了但它应该可以正常工作。它给你一个打字错误,我帮不了你那么多 我也不知道你是如何创建你的handleClick的,因为你没有分享它,这样很难帮助 ***.com/questions/29280445/… 因为当你可以像这样在组件中的函数时,你必须传递索引:props.handleClick(index),你试过我的代码吗?【参考方案2】:我是这样做的:
function DrawerMenuItems()
const [selectedIndex, setSelectedIndex] = React.useState("")
const handleClick = index =>
if (selectedIndex === index)
setSelectedIndex("")
else
setSelectedIndex(index)
return (
<List
component="nav"
aria-labelledby="nested-list-subheader"
subheader=
<ListSubheader component="div" id="nested-list-subheader">
Nested List Items
</ListSubheader>
>
drawerMenuItemData.map((item, index) =>
return (
<List>
<ListItem
key=index
button
onClick=() =>
handleClick(index)
>
<ListItemIcon>
<item.icon />
</ListItemIcon>
<ListItemText primary=item.title />
index === selectedIndex ? <ExpandLess /> : <ExpandMore />
</ListItem>
<Collapse in=index === selectedIndex timeout="auto" unmountOnExit>
<List component="div" disablePadding>
item.submenu.map((sub, index) =>
return (
<ListItem button >
<ListItemText primary=sub.name />
</ListItem>
)
)
</List>
</Collapse>
</List>
)
)
</List>
)
【讨论】:
我的也是这样解决的,但是我现在有一个问题,当你点击嵌套项目时如何让它保持打开状态? 在这种情况下,您可以在useState
中使用数组而不是字符串。然后只需将项目密钥存储在其中,并在折叠时将其删除。
非常感谢。 :)【参考方案3】:
您也可以使用 ant 设计的折叠组件。我用它做了一个嵌套的折叠组件。基本上,使用哪个库并不重要。重要的是您如何传递数据以及如何控制活动密钥。这是我的一个例子......
const ProductCatagoryHierarchy = () =>
const [tree, setTree] = useState([])
useEffect( async () =>
const arr2 = [
id: 1, name: 'gender', parent: null, parent_id: null ,
id: 2, name: 'material', parent: null, parent_id: null,
id: 3, name: 'male', parent: 1, parent_name: "gender" ,
id: 5, name: 'female', parent: 1, parent_name: "gender" ,
id: 4, name: 'shoe', parent: 3, parent_id: "male" ,
]
let newarr=[];
for(let i=0 ; i< arr2.length; i++ )
if(arr2[i].id)
if(newarr[i] != )
newarr[i] =
newarr[i].id = arr2[i].id
if( arr2[i].name )
newarr[i].name = arr2[i].name
if( arr2[i].parent )
newarr[i].parent = arr2[i].parent
if( arr2[i].parent_id )
newarr[i].parent_id = arr2[i].parent_id
newarr[i].products = arr2[i].products;
console.log('newarr', newarr );
let tree = function (data, root)
var t = ;
data.forEach(o =>
Object.assign(t[o.id] = t[o.id] || , o);
t[o.parent] = t[o.parent] || ;
t[o.parent].children = t[o.parent].children || [];
t[o.parent].children.push(t[o.id]);
);
return t[root].children;
(newarr, undefined);
console.log('tree ', tree);
setTree(tree)
, [])
const childFunc = (children) =>
// console.log('children', children );
let childPanel = children.map((child, i) =>
return(
<Collapse /* defaultActiveKey=child.id */
style= margin: '10px 0' key=i
expandIcon=( isActive ) =>
<CaretRightOutlined rotate=isActive ? 90 : 0 />
>
<Panel header=child.name key=child.id >
<p> child?.products?.length > 0 ?
<p> Products: <strong>
child.products.map(x => x.name ).join(', ')
</strong> </p> : 'No Product Available' </p>
child?.children?.length > 0 ?
childFunc(child.children) : null
</Panel>
</Collapse>
)
)
return childPanel;
return(
<div>
<h1> Category Hierarchy </h1>
/* <Button onClick=() => onclick() > test </Button> */
<Collapse >
tree.map((x,i,l) =>
console.log('x,i,l', x, i, l );
return(
<Panel header=x.name key=x.id
style= backgroundColor: 'darkgray' >
<p> x?.products?.length > 0 ?
<p> Products: <strong>
x.products.map(x => x.name).join(', ')
</strong> </p> : 'No Product Available' </p>
x?.children?.length > 0 ?
childFunc(x.children)
:
null
</Panel>
)
)
</Collapse>
</div>
)
export default ProductCatagoryHierarchy;
【讨论】:
以上是关于React Material UI 多重折叠的主要内容,如果未能解决你的问题,请参考以下文章
打字稿:React.forwardRef 带有来自@material-ui 的通用道具
Material-UI 中的多个展开/折叠 TableRow 组件