我正在尝试创建一个功能,以轻松隐藏/显示所有项目(子组件)。通过使用useState
,我可以设置是否隐藏/显示所有项目。通过使用useEffect
,我可以切换隐藏/显示的项目。我在访问子组件中的道具时遇到问题,以确定某个项目是否已经扩展。我希望我能对此做更好的解释,但是希望这个编码示例可以画出更好的图片。
index.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "semantic-ui-css/semantic.min.css";
import { Button } from "semantic-ui-react";
import Item from "./Item";
const Services = props => {
const [allExpanded, setAllExpanded] = useState(false);
return (
<>
<p>
<Button onClick={() => setAllExpanded(false)} content="Hide all" />
<Button onClick={() => setAllExpanded(true)} content="Show all" />
</p>
<p>
<Item expanded={allExpanded} />
<Item expanded={allExpanded} />
<Item expanded={allExpanded} />
</p>
</>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<Services />, rootElement);
Item.js
import React, { useState, useEffect } from "react";
import { Accordion } from "semantic-ui-react";
const Item = props => {
const [expanded, setExpanded] = useState(props.expanded);
useEffect(() => {
setExpanded(props.expanded);
}, [props.expanded]);
return (
<Accordion styled>
<Accordion.Title
onClick={() => {
setExpanded(!expanded);
}}
>
<p>{expanded ? "- Hide Item" : "+ Show Item"}</p>
</Accordion.Title>
<Accordion.Content active={expanded}>Lorem ipsum...</Accordion.Content>
</Accordion>
);
};
export default Item;
要复制我当前的错误,请单击任何“ +显示项”,然后单击“全部隐藏”。它不会隐藏所有内容,但是单击“全部显示”,然后单击“全部隐藏”将隐藏所有内容。
答案 0 :(得分:1)
您正面临此问题,因为您的父组件实际上具有三种可能的状态:
要反映第三个状态,可以使用null / undefined(并将setter传递到子组件中)。
答案 1 :(得分:0)
由于您正在顶层处理手风琴的扩展状态,因此建议您将扩展状态和“切换器”传递给您的商品。 index.js
将处理逻辑,而您的Item
组件将是演示性的。
这是您的CodeSandbox的分支。
它看起来不太好,并且项目状态和切换可能(可能应该)移动到其他地方(例如,使用useReducer
hook的单独的reducer)
如果您打算动态创建这些组件,那么IMO这是最简单的方法。
如果您仍然想走自己的路,可以将Item
重构为类组件,并使用Refs来获取其当前状态,但是我不推荐方法。
希望这会有所帮助!
答案 2 :(得分:0)
这是从您的代码中分叉出来的一个代码和沙箱:
https://codesandbox.io/s/competent-wildflower-n0hb8
我更改了它,以免出现类似这样的情况:
let [allExpanded, setAllExpanded] = useState(true)
您有类似这样的内容:
let [whichExpanded, setWhichExpanded] = useState({0: true, 1:true, 2: true})
然后,打开回调以展开/折叠所有按钮,您将得到:
<button onClick=()=>{
let newState = {}
for(let order in whichEpanded){
newState[order] = false //change every key to false
}
setAllExpanded(newState)
}> hide all</button>
然后,我为您的物品传递了一个“订购”道具。 “ order”道具用作我传递的回调函数的参数,因此,当您单击每个项目时,它会更新whichExpanded状态,以切换该项目的可见性。
// pass this to eac of the items:
const setIndividualItemExpanded = order => {
let newItemsExpandedState = { ...itemsExpanded };
newItemsExpandedState[order] = !newItemsExpandedState[order];
setItemsExpanded(newItemsExpandedState);
};
每个项目组成部分:
<Item
expanded={itemsExpanded[0]} //is reading from the state
order={0}
setExpanded={setIndividualItemExpanded}
/>
然后,您可以从呈现的组件中删除useState,而只需使用“ setExpanded”道具进行更新
(请参阅粘贴在顶部的代码和框中的完整代码)