hook作为react的新特性,解决了在组件之间复用状态逻辑很难的问题,无需修改组件结构的情况下,复用状态逻辑。
此处通过自定义hook,useOpenInsideCard实现多个子组件的开关复用一个state,实现多层抽屉效果。
在线效果 codesandbox.io/s/zi-ding-y…
父组件 (第一层抽屉)
import { useState } from "react";
import { Card } from "antd";
import { CaretDownOutlined, CaretUpOutlined } from "@ant-design/icons";
import "./styles.css";
import FirstCardOne from "./FirstCardOne";
import FirstCardTwo from "./FirstCardTwo";
// 第一层只打开一个抽屉
export default function App() {
const [openCardId, setOpenCardId] = useState(null);
return (
<div className="App">
<Card
title="第一层(1)"
bodyStyle={{ display: `${openCardId === 1 ? "block" : "none"}` }}
extra={
<span style={{ fontSize: "20px" }}>
{openCardId === 1 ? (
<CaretUpOutlined onClick={() => setOpenCardId(null)} />
) : (
<CaretDownOutlined onClick={() => setOpenCardId(1)} />
)}
</span>
}
>
<FirstCardOne showCard={openCardId === 1} />
<FirstCardTwo showCard={openCardId === 1} />
</Card>
<Card
title="第一层(2)"
bodyStyle={{ display: `${openCardId === 2 ? "block" : "none"}` }}
extra={
<span style={{ fontSize: "20px" }}>
{openCardId === 2 ? (
<CaretUpOutlined onClick={() => setOpenCardId(null)} />
) : (
<CaretDownOutlined onClick={() => setOpenCardId(2)} />
)}
</span>
}
>
第二层
</Card>
<Card
title="第一层(3)"
bodyStyle={{ display: `${openCardId === 3 ? "block" : "none"}` }}
extra={
<span style={{ fontSize: "20px" }}>
{openCardId === 3 ? (
<CaretUpOutlined onClick={() => setOpenCardId(null)} />
) : (
<CaretDownOutlined onClick={() => setOpenCardId(3)} />
)}
</span>
}
>
第二层
</Card>
</div>
);
}
自定义hook, useOpenInsideCard
import { useState, useEffect } from "react";
export default function useOpenInsideCard(showCard) {
const [openInsideCard, setOpenInsideCard] = useState(false);
useEffect(() => {
if (!showCard) {
setOpenInsideCard(false);
}
}, [showCard]);
return [openInsideCard, setOpenInsideCard];
}
子组件 第二层抽屉
第一层关闭后,第二次里面的抽屉全部关闭
父组件卡片关闭,所有的子组件里面的所有的卡片需要关闭。并且子组件也可以单独控制自己的开关。
子组件使用以上自定义hook,useOpenInsideCard,实现开关控制
(做多层抽屉时,原理一样,可同样处理)
import { Card } from "antd";
import { CaretDownOutlined, CaretUpOutlined } from "@ant-design/icons";
import useOpenInsideCard from "./useOpenInsideCard";
export default function FirstCardOne(prop) {
const { showCard } = prop;
const [openInsideCard, setOpenInsideCard] = useOpenInsideCard(showCard);
return (
<Card
title="第二层(1)"
bodyStyle={{ display: `${openInsideCard ? "block" : "none"}` }}
extra={
<span
style={{ fontSize: "20px" }}
onClick={() => {
const newOpenTime = !openInsideCard;
setOpenInsideCard(newOpenTime);
}}
>
{openInsideCard ? <CaretUpOutlined /> : <CaretDownOutlined />}
</span>
}
>
this is a test 1.1
</Card>
);
}